[luogu2154 SDOI2009] 虔誠的墓主人(樹狀數組+組合數)
阿新 • • 發佈:2018-10-14
得到 sdoi2009 define lin 思路 fin size set new
傳送門
Solution
顯然每個點的權值可以由當前點上下左右的樹的數量用組合數\(O(1)\)求出,但這樣枚舉會T
那麽我們考慮一段連續區間,對於一行中兩個常青樹中間的部分左右樹的數量一定,我們可用樹狀數組求區上下貢獻值和,相乘就得到了當前區間的貢獻。
有思路調不出來系列
Code
#include <cmath> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define Re register #define Ms(a,b) memset(a,(b),sizeof(a)) #define Fo(i,a,b) for(Re int i=(a),_=(b);i<=_;i++) #define Ro(i,a,b) for(Re int i=(b),_=(a);i>=_;i--) using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char c=getchar(); while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();} while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar(); return x*f; } const int MAXW=1e5+5; int n,m,W,lx,k,N; int dx[MAXW],wx[MAXW],d[MAXW],l[MAXW],u[MAXW],r[MAXW]; LL ans,Cc[MAXW][13]; struct Tree{int x,y,id;}T[MAXW]; struct BIT{ LL da[MAXW]; BIT() {clear();} void clear() {Ms(da,0);} void add(int x,LL d) {for(;x<=lx;x+=x&-x)da[x]+=d;} LL qry(int x) {LL t=0;for(;x;x-=x&-x)t+=da[x];return t;} }B; bool cmpx(Tree a,Tree b) {return a.x==b.x?a.y<b.y:a.x<b.x;} bool cmpy(Tree a,Tree b) {return a.y==b.y?a.x<b.x:a.y<b.y;} void init() { sort(T+1,T+1+W,cmpx); Fo(i,1,W) { int j=i,now=0; while(T[j+1].x==T[j].x) j++,d[T[j].id]=++now; while(i<=j) u[T[i].id]=now--,i++; i--; N=max(N,d[T[j].id]); } sort(T+1,T+1+W,cmpy); Fo(i,1,W) { int j=i,now=0; while(T[j+1].y==T[j].y) j++,l[T[j].id]=++now; while(i<=j) r[T[i].id]=now--,i++; i--; N=max(N,l[T[j].id]); } Fo(i,0,N) Cc[i][0]=Cc[i][i]=1; Fo(i,2,N) Fo(j,1,k) Cc[i][j]=Cc[i-1][j]+Cc[i-1][j-1]; sort(dx+1,dx+1+lx); lx=unique(dx+1,dx+1+lx)-dx-1; Fo(i,1,W) wx[i]=lower_bound(dx+1,dx+1+lx,T[i].x)-dx; } LL C(int x) {return Cc[x][k];} int main() { n=read()+1; m=read()+1; W=read(); Fo(i,1,W) dx[++lx]=T[i].x=read()+1,T[i].y=read()+1,T[i].id=i; k=read(); init(); for(Re int i=1,j;i<=W;i=j+1) { j=i; B.add(wx[i],C(d[T[i].id]+1)*C(u[T[i].id])-C(d[T[i].id])*C(u[T[i].id]+1)); while(T[j+1].y==T[i].y) { j++; ans+=C(l[T[j-1].id]+1)*C(r[T[j].id]+1)*(B.qry(wx[j]-1)-B.qry(wx[j-1])); B.add(wx[j],C(d[T[j].id]+1)*C(u[T[j].id])-C(d[T[j].id])*C(u[T[j].id]+1)); } } printf("%d",ans&2147483647);//自然溢出,可以有效簡化代碼,但易出錯,慎用 return 0; }
[luogu2154 SDOI2009] 虔誠的墓主人(樹狀數組+組合數)