【SYZOI Round1】滑稽的树

Description

zzsyz实验楼里面种了一棵滑稽树,只有滑稽之力达到大乘期的oier才能看到。虽然我们看不到,但是还是知道一些信息:
这真的是一棵树,由n个节点,n-1条边联通。一号滑稽果同时也是整棵滑稽树的树根。滑稽树上每个节点有一个滑稽果,每个滑稽果有它的重量。
雪甜甜公主是神犇当然看得到那棵滑稽树啦,现在她感兴趣的是这样三件事
1:滑稽树太大啦,雪甜甜公主有的时候只想知道,在以某一个滑稽果为根的子滑稽树里面,重量第k小的果子的重量是多少?
2:除了重量第k小的果子,雪甜甜还想知道以某个滑稽果为根的子滑稽树里面,重量在[a, b]这个范围内的滑稽果有多少个。
3:雪甜甜还喜欢吃滑稽果,但是吃完,原来滑稽果的位置上还会长出一个新的滑稽果,只是重量可能不一样。

Input

第一行一个正整数n,表示滑稽树有n个节点。
第二行n个正整数,分别描述1号,2号,,,,n号节点滑稽果的重量。
接下来n-1行,每行2个正整数u, v ∈ [1, n],表示滑稽果u与滑稽果v之间有树枝连接。
接下来一个正整数q,表示雪甜甜有q次行动
之后q行,有这样3种形式
1 u k 雪甜甜公主询问以u为根的子滑稽树中,重量第k小的滑稽果的重量。
2 u a b 雪甜甜公主想知道,以u为根的子滑稽树中,重量在[a, b]范围内的滑稽果有多少个。
3 u x 雪甜甜公主吃掉了编号为u的滑稽果,但是在原位置上立刻长出来了一个重量为x的滑稽果。因为位置没有变,所以编号还是u。

Output

对于每次询问,输出结果。

Sample Input

5
3 4 6 1 2
1 2
1 3
3 4
3 5
7
1 1 4
2 1 1 5
3 4 5
1 1 4
2 3 3 6
3 5 7
1 3 3

Sample Output

4
4
5
2
7

Hint

样例提示:
P

数据的范围及提示:
N:
对于前35%的数据满足,N <= 5000
对于前50%的数据满足,N <= 10000
对于前100%的数据满足,N <= 30000
滑稽果的重量:对于100%d的数据满足 滑稽果的重量 <= 10000
询问:询问的个数Q:
对于前50%的数据满足 Q <= 10000
对于前100%的数据满足 Q <= 50000
对于前25%的数据,只有第一种询问。
对于前65%的数据,有第1,2种询问。
对于100%的数据第1,2,3种询问都存在。
对于前35%的数据,满足一个特殊的限制条件:每次询问的滑稽果u = 1保证询问k小重量的滑稽果的时候,k值∈ [1, 子树的节点数]

 

题解:

变样的整体二分,直接记录进出子树的时间戳就可以转化为区间问题,

值得注意的是查找[L,R]的个数 的地方很细节.

只有t[i].k>mid 时才可以统计,不能取等,不然就会被加入到q1 然后被重复统计

 

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 using namespace std;
  8 const int N=30005,M=50005,Q=M*2+N;
  9 const int INF=-2e8;
 10 int head[N],num=0;
 11 struct Lin{
 12     int next,to;
 13 }b[N<<1];
 14 void init(int x,int y){
 15     b[++num].next=head[x];
 16     b[num].to=y;
 17     head[x]=num;
 18 }
 19 int gi(){
 20     int str=0;char ch=getchar();
 21     while(ch>'9' || ch<'0')ch=getchar();
 22     while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
 23     return str;
 24 }
 25 int n,m,val[N];
 26 struct node{
 27     int ki,x,y,k,cnt,id;
 28 }t[Q<<1],q1[Q<<1],q2[Q<<1];
 29 int dfn[N],last[N],dfns=0,tot=0;
 30 void dfs(int x){
 31         dfn[x]=++dfns;
 32         for(int i=head[x];i;i=b[i].next){
 33                 if(!dfn[b[i].to])dfs(b[i].to);
 34         }
 35         last[x]=dfns;
 36 }
 37 int a[N],ans[M],Tree[N*4];
 38 void add(int sta,int ad){
 39     for(int i=sta;i<=n;i+=(i&(-i)))Tree[i]+=ad;
 40 }
 41 int getsum(int sta){
 42     int sum=0;
 43     for(int i=sta;i>=1;i-=(i&(-i)))sum+=Tree[i];
 44     return sum;
 45 }
 46 int l1,l2;
 47 void count(int ll,int rr,int dl,int dr)
 48     {
 49         l1=l2=0;
 50         for(int i=ll;i<=rr;i++)
 51             {
 52                 if(t[i].ki==1)
 53                     {
 54                         t[i].cnt=getsum(t[i].y)-getsum(t[i].x-1);
 55                         if(t[i].cnt>=t[i].k)q1[++l1]=t[i];
 56                         else t[i].k-=t[i].cnt,q2[++l2]=t[i];
 57                     }
 58                 else if(t[i].ki==2)
 59                     {
 60                         if(t[i].k>dr)
 61                             ans[t[i].id]+=(getsum(t[i].y)-getsum(t[i].x-1))*t[i].cnt,q2[++l2]=t[i];
 62                         else
 63                             q1[++l1]=t[i];
 64                     }
 65                 else
 66                     {
 67                         if(t[i].y<=dr)add(t[i].x,t[i].cnt),q1[++l1]=t[i];
 68                         else q2[++l2]=t[i];
 69                     }
 70              }
 71         for(int i=1;i<=l1;i++)
 72             if(q1[i].ki==3)
 73                 add(q1[i].x,-q1[i].cnt);
 74    int now=ll-1;
 75         for(int i=1;i<=l1;i++)
 76             t[++now]=q1[i];
 77         for(int i=1;i<=l2;i++)
 78             t[++now]=q2[i];
 79     }
 80 void div(int ll,int rr,int dl,int dr)
 81     {
 82         if(dl==dr){
 83             for(int i=ll;i<=rr;i++)
 84                 if(t[i].ki==1)ans[t[i].id]=dl;
 85             return ;
 86         }
 87         int mid=(dl+dr)>>1;
 88         count(ll,rr,dl,mid);
 89         int p=l1;
 90         if(p)
 91             div(ll,ll+p-1,dl,mid);
 92         if(p<=rr-ll)
 93             div(ll+p,rr,mid+1,dr);
 94     }
 95 int main()
 96 {
 97     n=gi();
 98     for(int i=1;i<=n;i++)
 99         val[i]=gi();
100     int x,y;
101     for(int i=1;i<n;i++){
102         x=gi();y=gi();
103         init(x,y);init(y,x);
104     }
105     dfs(1);
106     for(int i=1;i<=n;i++){
107         a[dfn[i]]=val[i];
108         t[++tot]=(node){3,dfn[i],val[i],0,1,0};
109     }
110     m=gi();
111     int flag,z,qnum=0;
112     for(int i=1;i<=m;i++)
113         {
114             flag=gi();
115             if(flag==1){
116                     x=gi();y=gi();
117                     t[++tot]=(node){1,dfn[x],last[x],y,0,++qnum};
118                 }
119             else
120                 if(flag==2){
121                     x=gi();y=gi();z=gi();
122                     t[++tot]=(node){2,dfn[x],last[x],y,-1,++qnum};
123                     t[++tot]=(node){2,dfn[x],last[x],z+1,1,qnum};
124                 }
125                 else{
126                     x=gi();y=gi();
127                     t[++tot]=(node){3,dfn[x],a[dfn[x]],0,-1,0};
128                     t[++tot]=(node){3,dfn[x],y,0,1,0};
129                     a[dfn[x]]=y;
130                 }
131         }
132     div(1,tot,0,10000);
133     for(int i=1;i<=qnum;i++)printf("%d\n",ans[i]);
134     return 0;
135 }

 

posted @ 2017-07-03 20:25  PIPIBoss  阅读(299)  评论(0编辑  收藏  举报