1. 程式人生 > >luogu3242 接水果 (整體二分+樹狀數組)

luogu3242 接水果 (整體二分+樹狀數組)

color air += out 就是 過去 amp names type

考慮整體二分,問題就變成了每個(水果)路徑有多少個滿足條件(權值)的(盤子)子路徑

考慮一個盤子(a,b)表示兩端點(不妨設dfn[a]<dfn[b]),那麽他能接到的水果(u,v)一定滿足(不妨設dfn[u]<dfn[v]):

1.如果a是b的祖先,則u在(a的在(b,a)鏈上的孩子)這個子樹外,v在b子樹內

2.否則,u在a的子樹內,v在b的子樹內

那麽把一個水果(a,b)看成是一個二維點(dfn[a],dfn[b]),對於每個盤子,就是做一個二維區間+1

差分以後變成一個二維數點問題,可以先按x排序,y用樹狀數組來解決

復雜度$O(nlog^2n)$

然而我寫的常數過大哪都卡不過去

  1 #include<bits/stdc++.h>
  2 #define CLR(a,x) memset(a,x,sizeof(a))
  3 #define MP make_pair
  4 using namespace std;
  5 typedef long long ll;
  6 typedef unsigned long long ull;
  7 typedef pair<int,int> pa;
  8 const int maxn=4e4+10,maxp=1e7+10;
  9 
 10 inline ll rd(){
 11
ll x=0;char c=getchar();int neg=1; 12 while(c<0||c>9){if(c==-) neg=-1;c=getchar();} 13 while(c>=0&&c<=9) x=x*10+c-0,c=getchar(); 14 return x*neg; 15 } 16 17 int N,P,Q; 18 int eg[maxn*2][2],egh[maxn],ect; 19 int dfn[maxn][2],tot; 20 int rt[maxn],fa[maxn][20
],dep[maxn]; 21 int tr[maxn]; 22 23 inline int lowbit(int x){return x&(-x);} 24 25 inline void add(int x,int d){ 26 for(;x&&x<=N;x+=lowbit(x)) tr[x]+=d; 27 } 28 inline int query(int x){ 29 int re=0; 30 for(;x;x-=lowbit(x)) re+=tr[x]; 31 return re; 32 } 33 34 inline void adeg(int a,int b){ 35 eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect; 36 } 37 38 inline void dfs(int x){ 39 for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++){ 40 fa[x][i+1]=fa[fa[x][i]][i]; 41 } 42 dfn[x][0]=++tot; 43 for(int i=egh[x];i;i=eg[i][1]){ 44 int b=eg[i][0];if(b==fa[x][0]) continue; 45 fa[b][0]=x,dep[b]=dep[x]+1; 46 dfs(b); 47 }dfn[x][1]=tot; 48 } 49 50 inline int jump(int x,int d){ 51 for(int i=0;d;i++,d>>=1){ 52 if(d&1) x=fa[x][i]; 53 }return x; 54 } 55 56 int ans[maxn],nct; 57 pa val[maxn]; 58 struct Node{ 59 int a,b,d,v,i; 60 }op[maxn*9],tmp[maxn*9]; 61 62 inline void addnode(int x1,int x2,int y1,int y2,int v,int i){ 63 op[++nct]=(Node){x1,y1,1,v,i}; 64 if(x2<N&&y2<N) op[++nct]=(Node){x2+1,y2+1,1,v,i}; 65 if(x2<N) op[++nct]=(Node){x2+1,y1,-1,v,i}; 66 if(y2<N) op[++nct]=(Node){x1,y2+1,-1,v,i}; 67 } 68 69 inline void cover(int a,int b,int v,int i){ 70 if(dfn[a][0]>dfn[b][0]) swap(a,b); 71 if(dfn[a][1]>=dfn[b][1]){ 72 int x=jump(b,dep[b]-dep[a]-1); 73 addnode(1,dfn[x][0]-1,dfn[b][0],dfn[b][1],v,i); 74 addnode(dfn[b][0],dfn[b][1],dfn[x][1]+1,N,v,i); 75 }else{ 76 addnode(dfn[a][0],dfn[a][1],dfn[b][0],dfn[b][1],v,i); 77 } 78 } 79 80 inline void solve(int l,int r,int ql,int qr){ 81 if(l>r||ql>qr) return; 82 int m=ql+qr>>1; 83 // printf("~%d %d %d %d %d\n",l,r,ql,qr,val[m]); 84 int p=l-1,q=r+1; 85 for(int i=l;i<=r;i++){ 86 if(op[i].d){ 87 if(MP(op[i].v,op[i].i)<=val[m]){ 88 add(op[i].b,op[i].d); 89 tmp[++p]=op[i]; 90 }else tmp[--q]=op[i]; 91 }else{ 92 int n=query(op[i].b); 93 if(n>=op[i].v){ 94 ans[op[i].i]=val[m].first; 95 tmp[++p]=op[i]; 96 }else if(n<op[i].v){ 97 op[i].v-=n; 98 tmp[--q]=op[i]; 99 } 100 } 101 102 } 103 for(int i=l;i<=r;i++){ 104 if(op[i].d){ 105 if(MP(op[i].v,op[i].i)<=val[m]){ 106 add(op[i].b,-op[i].d); 107 } 108 } 109 } 110 for(int i=l;i<=p;i++) op[i]=tmp[i]; 111 for(int i=q;i<=r;i++) op[r-i+q]=tmp[i]; 112 solve(l,p,ql,m-1),solve(q,r,m+1,qr); 113 } 114 115 inline bool cmp(Node a,Node b){return a.a==b.a?a.d!=0:a.a<b.a;} 116 117 int main(){ 118 // freopen("fruit1.in","r",stdin); 119 // freopen("aa.out","w",stdout); 120 int i,j,k; 121 N=rd(),P=rd(),Q=rd(); 122 for(i=1;i<N;i++){ 123 int a=rd(),b=rd(); 124 adeg(a,b);adeg(b,a); 125 } 126 dep[1]=1;dfs(1); 127 for(i=1;i<=P;i++){ 128 int a=rd(),b=rd(),c=rd(); 129 val[i]=MP(c,i); 130 cover(a,b,c,i); 131 }sort(val+1,val+P+1); 132 for(i=1;i<=Q;i++){ 133 int a=rd(),b=rd(),c=rd(); 134 if(dfn[a][0]>dfn[b][0]) swap(a,b); 135 op[++nct]=(Node){dfn[a][0],dfn[b][0],0,c,i}; 136 } 137 sort(op+1,op+nct+1,cmp); 138 solve(1,nct,1,P); 139 for(i=1;i<=Q;i++) printf("%d\n",ans[i]); 140 return 0; 141 }

luogu3242 接水果 (整體二分+樹狀數組)