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

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

考虑一个盘子(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 }

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

时间: 2024-11-08 20:23:03

luogu3242 接水果 (整体二分+树状数组)的相关文章

【bzoj2527】[Poi2011]Meteors 整体二分+树状数组

题目描述 有N个成员国.现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会下陨石雨.BIU已经预测了接下来K场陨石雨的情况.BIU的第i个成员国希望能够收集Pi单位的陨石样本.你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石. 输入 第一行是两个数N,M. 第二行有M个数,第i个数Oi表示第i段轨道上有第Oi个国家的太空站. 第三行有N个数,第i个数Pi表示第i个国家希望收集的陨石数量. 第四行有一个

【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 HINT

【BZOJ-2527】Meteors 整体二分 + 树状数组

2527: [Poi2011]Meteors Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 831  Solved: 306[Submit][Status][Discuss] Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colo

【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改

题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. 输入 第一行N,M接下来M行,每行形如1 a b c或2 a b c 输出 输出每个询问的结果 样例输入 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 样例输出 1 2 1 题解 整体二分+树状数组区间修改 当年naive的树套树题解 前两天由于要

bzoj 2527 Meteors - 整体二分 - 树状数组

Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colonisation due to strange meteor showers, which on the other hand make it an exceptionally interesting object of st

【POJ2104】【整体二分+树状数组】区间第k大

Description You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array

BZOJ_3110_[Zjoi2013]K大数查询_整体二分+树状数组

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 solve

11525 - Permutation(二分+树状数组)

题目链接:点击打开链接 题意:从1~k的所有排列中找到第n个排列, n由公式给出. 思路:可以发现, 这个公式就是康托展开公式(康托展开百科:点击打开链接). 那么s[i]的意思就是i个数中当前数排在第几. 如此, 可以用二分+树状数组快速求解, 和一道BC题目神似. 细节参见代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<st

Codeforces 374D Inna and Sequence 二分+树状数组

题目链接:点击打开链接 给定n个操作,m长的序列a 下面n个数 if(co>=0)则向字符串添加一个co (开始是空字符串) else 删除字符串中有a的下标的字符 直接在序列上搞,简单模拟 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h&