• 【块状树】bzoj3720 Gty的妹子树


    块状树。
    教程见:http://z55250825.blog.163.com/blog/static/1502308092014163413858/
    将树按一定大小分块,分成许多子树,在每个子树的根节点记录一个数组,存储这个块中数据的有序表,查询时二分即可。

    对于添加节点操作,若添加的节点的父节点所在块大小没有超过size,则添加到上面的块里,否则另起一块。

    这个size值要注意,由于有二分操作,所以大小定为sqrt(n*log2(n))比较好,而不是sqrt(n),证明略。

    时间复杂度O(n*sqrt(n)*log(sqrt(n)))。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cmath>
      4 #include<vector>
      5 using namespace std;
      6 #define maxn 60001
      7 typedef vector<int>::iterator ITER;
      8 vector<int>List[maxn],Goto[maxn];
      9 int res,CH[20],Num;char c;
     10 inline int Ge()
     11 {
     12     res=0;c='*';
     13     while(c<'0'||c>'9')c=getchar();
     14     while(c>='0'&&c<='9'){res=res*10+(c-'0');c=getchar();}
     15     return res;
     16 }
     17 inline void P(int x)
     18 {
     19     if(!x){putchar('0');puts("");return;}Num=0;
     20     while(x>0){CH[++Num]=x%10;x/=10;}
     21     while(Num)putchar(CH[Num--]+48);
     22     putchar('
    ');
     23 }
     24 struct Graph
     25 {
     26     int v[maxn<<1],first[maxn<<1],next[maxn<<1],en;
     27     void AddEdge(const int &a,const int &b)
     28     {v[++en]=b;next[en]=first[a];first[a]=en;}
     29 };
     30 Graph G,son;
     31 int top[maxn],siz[maxn],sz,w[maxn];
     32 bool vis[maxn];
     33 int n,x,y,m,op;
     34 int ans,val,U;
     35 void makeblock(int cur)
     36 {
     37     vis[cur]=true;
     38     for(int i=G.first[cur];i;i=G.next[i])
     39       if(!vis[G.v[i]])
     40         {
     41           son.AddEdge(cur,G.v[i]);
     42           if(siz[top[cur]]<sz)
     43             {
     44               List[top[cur]].push_back(w[G.v[i]]);
     45               siz[top[cur]]++;
     46               top[G.v[i]]=top[cur];
     47             }
     48           makeblock(G.v[i]);
     49         }
     50 }
     51 void makeGoto(int cur)
     52 {
     53     for(int i=son.first[cur];i;i=son.next[i])
     54       {
     55           if(top[son.v[i]]!=top[cur])
     56           Goto[top[cur]].push_back(son.v[i]);
     57         makeGoto(son.v[i]);
     58       }
     59 }
     60 void dfs(int cur)
     61 {
     62     ans+=( List[cur].end() - upper_bound( List[cur].begin() , List[cur].end() , val ) );
     63     for(ITER it=Goto[cur].begin();it!=Goto[cur].end();it++)
     64       dfs(*it);
     65 }
     66 void dfs_block(int cur)
     67 {
     68     if(w[cur]>val) ans++;
     69     for(int i=son.first[cur];i;i=son.next[i])
     70       if(top[son.v[i]]==top[cur]) dfs_block(son.v[i]);
     71       else dfs(son.v[i]);
     72 }
     73 void query()
     74 {
     75     ans=0;
     76     if(U==top[U]) dfs(U);
     77     else dfs_block(U);
     78     P(ans);
     79 }
     80 void update()
     81 {
     82     List[top[U]].erase( lower_bound(List[top[U]].begin(),List[top[U]].end(),w[U]) );
     83     w[U]=val;
     84     List[top[U]].insert( lower_bound(List[top[U]].begin(),List[top[U]].end(),val+1) , val );
     85 }
     86 void AddPoint()
     87 {
     88     n++;
     89     if(siz[top[U]]<sz)
     90       {
     91           top[n]=top[U];
     92           siz[top[n]]++;
     93       }
     94     else
     95       {
     96           top[n]=n;
     97           siz[n]++;
     98           Goto[top[U]].push_back(n);
     99       }
    100     son.AddEdge(U,n);
    101     w[n]=val;
    102     List[top[n]].insert( lower_bound(List[top[n]].begin(),List[top[n]].end(),val+1) , val );
    103 }
    104 int main()
    105 {
    106     n=Ge();
    107     for(int i=1;i<n;i++)
    108       {
    109           x=Ge();y=Ge();
    110           G.AddEdge(x,y);
    111           G.AddEdge(y,x);
    112       }
    113     sz=sqrt((double)n*log2(n));
    114     for(int i=1;i<=n;i++)
    115       {
    116           w[i]=Ge();
    117           top[i]=i;
    118           siz[i]=1;
    119       }
    120     makeblock(1);
    121     for(int i=1;i<=n;i++)
    122       if(top[i]==i)
    123         {
    124           List[i].push_back(w[i]);
    125           sort(List[i].begin(),List[i].end());
    126         }
    127     makeGoto(1);
    128     m=Ge();
    129     for(int i=1;i<=m;i++)
    130       {
    131           op=Ge();U=Ge();val=Ge();U^=ans;val^=ans;
    132           if(!op)query();
    133           else if(op==1)update();
    134           else AddPoint();
    135       }
    136     return 0;
    137 }
  • 相关阅读:
    word-wrap和word-break的区别
    transform 二维转变
    过渡
    新闻下滑导航案例
    background-origin,clip
    边框图片
    背景样式
    线性渐变与径向渐变与重复渐变
    边框阴影
    盒模型和圆角
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/3984165.html
Copyright © 2020-2023  润新知