码迷,mamicode.com
首页 > 编程语言 > 详细

luogu3242 接水果 (整体二分+树状数组)

时间:2018-12-01 20:26:16      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:nbsp   val   for   first   eof   efi   路径   c++   log   

考虑整体二分,问题就变成了每个(水果)路径有多少个满足条件(权值)的(盘子)子路径

考虑一个盘子(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 接水果 (整体二分+树状数组)

标签:nbsp   val   for   first   eof   efi   路径   c++   log   

原文地址:https://www.cnblogs.com/Ressed/p/10050585.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!