zoukankan      html  css  js  c++  java
  • 【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
    ",ans[i]);
    134     return 0;
    135 }
  • 相关阅读:
    (转载)敏捷开发一千零一问系列之三十三:每天编码多少行?
    (转载)memcpy的几个实现版本
    (转载)HTTP URL
    (转载)C++lambda表达式
    (转载)程序员面试什么最重要?
    (转载)static全局变量与普通的全局变量有什么区别?
    (转载)【C++】new A和new A()的区别详解
    (转载)php如何判断IP为有效IP地址
    查看修复HDFS中丢失的块
    dfs.replication、dfs.replication.min/max及dfs.safemode.threshold.pct
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7112895.html
Copyright © 2011-2022 走看看