zoukankan      html  css  js  c++  java
  • BZOJ3720 Gty的妹子树

    Description

    我曾在弦歌之中听过你,

    檀板声碎,半出折子戏。

    舞榭歌台被风吹去,

    岁月深处尚有余音一缕……


    Gty神(xian)犇(chong)从来不缺妹子……

    他来到了一棵妹子树下,发现每个妹子有一个美丽度……

    由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣。

    他想知道某个子树中美丽度大于k的妹子个数。

    某个妹子的美丽度可能发生变化……

    树上可能会出现一只新的妹子……


    维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。

    支持以下操作:

    0 u x          询问以u为根的子树中,严格大于x的值的个数。(u^=lastans,x^=lastans)

    1 u x          把u节点的权值改成x。(u^=lastans,x^=lastans)

    2 u x          添加一个编号为"当前树中节点数+1"的节点,其父节点为u,其权值为x。(u^=lastans,x^=lastans)

    最开始时lastans=0。

    Input

    输入第一行包括一个正整数n(1<=n<=30000),代表树上的初始节点数。

    接下来n-1行,每行2个整数u,v,为树上的一条无向边。

    任何时刻,树上的任何权值大于等于0,且两两不同。

    接下来1行,包括n个整数wi,表示初始时每个节点的权值。

    接下来1行,包括1个整数m(1<=m<=30000),表示操作总数。

    接下来m行,每行包括三个整数 op,u,v:

    op,u,v的含义见题目描述。

    保证题目涉及的所有数在int内。

    Output

    对每个op=0,输出一行,包括一个整数,意义见题目描述。

    Sample Input

    2
    1 2
    10 20
    1
    0 1 5

    Sample Output

    2

    正解:块状树

    解题报告:

      遥遥昨天讲了许多神奇的数据结构,比如这道题用的块状树,个人感觉就是在树上分块。。。

      大概讲一下块状树的思想和用法吧。考虑我们将树上的某一些点变成一个连通块,然后每个块中分别处理(内部都是暴力处理),如果碰到可以整块处理的就整块处理。

      每个块都记录一下块内的权值,按顺序排列。块与块之间有连边。

      感觉跟分块真的很像。。。第一遍DFS的时候看一下父亲所在的块是否已经满了(设置为块的上限,在根号左右最佳),如果满了的话就新建一个块,并且把新建的块与父亲所在的块连边,否则加入父亲所在的块。每次插入,在块内部都是暴力处理。修改操作也是在块内暴力处理,修改完之后暴力移动,保证有序性。新的插入也是一样的,与第一遍DFS相同,只需看一下父亲所在块是不是满了。查询的话就DFS,发现儿子结点与自己所在块不同,就直接访问整个块,二分查找块内大于需查询的值的个数。

      这道题有很多细节要注意,调了一个多小时,中间经历了WA、RE、TLE、MLE,也是醉了。

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 #ifdef WIN32   
     14 #define OT "%I64d"
     15 #else
     16 #define OT "%lld"
     17 #endif
     18 using namespace std;
     19 typedef long long LL;
     20 const int MAXN = 60011; 
     21 const int S = 400; //实验表明,400附近最合适。。。
     22 int n,ecnt,cnt;
     23 int w[MAXN],father[MAXN];
     24 int first[MAXN],next[MAXN*2],to[MAXN*2];
     25 int ans,m;
     26 int belong[MAXN];
     27 int head[MAXN];
     28 
     29 inline int getint()
     30 {
     31        int w=0,q=0;
     32        char c=getchar();
     33        while((c<'0' || c>'9') && c!='-') c=getchar();
     34        if (c=='-')  q=1, c=getchar();
     35        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     36        return q ? -w : w;
     37 }
     38 
     39 struct kuai_tree{
     40     int size; int a[S+12];
     41 
     42     inline void insert(int x){//块内暴力插入新元素
     43     size++; int i=size;
     44     for(;i>=2;i--) if(a[i-1]>x) a[i]=a[i-1]; else break;
     45     a[i]=x;
     46     }
     47 
     48     inline int zuo_ask(int x){//查找到相等的值的最左一位
     49     int l=1,r=size,mid;
     50     while(l<=r) {
     51         mid=(l+r)/2;
     52         if(a[mid]>=x) r=mid-1;
     53         else l=mid+1;
     54     }
     55     return l;//!!!
     56     }
     57 
     58     inline int you_ask(int x){//查找到相等的值的最右一位
     59     int l=1,r=size,mid;
     60     while(l<=r) {
     61         mid=(l+r)/2;
     62         if(a[mid]>x) r=mid-1;
     63         else l=mid+1;
     64     }
     65     return r;//!!!
     66     }
     67 
     68     inline void update(int x,int y){//块内暴力更改
     69     int i=zuo_ask(x);
     70     for(;i<size && a[i+1]<y;i++) a[i]=a[i+1];
     71     for(;i>1 && a[i-1]>y;i--) a[i]=a[i-1];//无需等号
     72     a[i]=y;
     73     }
     74 
     75     inline int query(int x){
     76     return size-you_ask(x);
     77     }
     78 }tr[MAXN];
     79 
     80 inline void link(int x,int y){ next[++ecnt]=head[x]; head[x]=ecnt; to[ecnt]=y; }
     81 
     82 inline void dfs(int x,int fa){
     83     if(tr[belong[fa]].size==S) {cnt++; belong[x]=cnt; link(belong[fa],cnt); tr[cnt].insert(w[x]);}//是belong而不是本身!!! 是cnt而不是本身
     84     else { belong[x]=belong[fa]; tr[belong[fa]].insert(w[x]); }
     85     father[x]=fa;
     86     for(int i=first[x];i;i=next[i]) {
     87     int v=to[i];
     88     if(v==fa) continue;
     89     dfs(v,x);
     90     }
     91 }
     92 
     93 inline void kuai_DFS(int x,int num){
     94     ans+=tr[x].query(num);
     95     for(int i=head[x];i;i=next[i]) kuai_DFS(to[i],num);
     96 }
     97 
     98 inline void DFS(int x,int num){
     99     if(w[x]>num) ans++;
    100     for(int i=first[x];i;i=next[i]) {
    101     int v=to[i];
    102     if(v==father[x]) continue;
    103     if(belong[x]==belong[v]) DFS(v,num);
    104     else kuai_DFS(belong[v],num);
    105     }
    106 }
    107 
    108 inline void work(){
    109     n=getint();  int x,y;
    110     for(int i=1;i<n;i++) {
    111     x=getint(); y=getint();
    112     next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
    113     next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x;
    114     }
    115     for(int i=1;i<=n;i++) w[i]=getint();
    116     tr[0].size=S; dfs(1,0);
    117     m=getint(); int ljh;
    118     for(int i=1;i<=m;i++) {
    119     ljh=getint(); x=getint(); y=getint();
    120     x=x^ans; y=y^ans;
    121     if(ljh==0) { ans=0; DFS(x,y); printf("%d
    ",ans); }
    122     else if(ljh==1) { tr[belong[x]].update(w[x],y); w[x]=y; }
    123     else{
    124         w[++n]=y; father[n]=x;  next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=n;//都要连接一下
    125         if(tr[belong[x]].size==S) {
    126         cnt++; tr[cnt].insert(y); belong[n]=cnt; 
    127         link(belong[x],cnt); 
    128         }
    129         else{
    130         belong[n]=belong[x];        
    131         tr[belong[x]].insert(y); 
    132         }
    133     }
    134     }
    135 }
    136 
    137 int main()
    138 {
    139   work();
    140   return 0;
    141 }
  • 相关阅读:
    【梦断代码】与我们队的相似之处
    梦断代码 之 你失败过吗
    梦断代码 之 程序人生
    C#中父类转换为子类
    C#中Dictionary泛型集合7种常见的用法
    Linux 常见命令 目录处理指令
    使用XSLT+XML生成网页
    我心目中的Asp.net核心对象
    配色速成
    VS.NET中JavaScript隐藏特性
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5692034.html
Copyright © 2011-2022 走看看