3720: Gty的妹子树
3720: Gty的妹子樹
Time Limit:?10 Sec??Memory Limit:?128 MBSubmit:?1440??Solved:?482
[Submit][Status][Discuss]
Description
我曾在弦歌之中聽過你,
檀板聲碎,半出折子戲。
舞榭歌臺被風吹去,
歲月深處尚有余音一縷……
Gty神(xian)犇(chong)從來不缺妹子……
他來到了一棵妹子樹下,發(fā)現每個妹子有一個美麗度……
由于Gty很哲♂學,他只對美麗度大于某個值的妹子感興趣。
他想知道某個子樹中美麗度大于k的妹子個數。
某個妹子的美麗度可能發(fā)生變化……
樹上可能會出現一只新的妹子……
維護一棵初始有n個節(jié)點的有根樹(根節(jié)點為1),樹上節(jié)點編號為1-n,每個點有一個權值wi。
支持以下操作:
0 u x????????? 詢問以u為根的子樹中,嚴格大于x的值的個數。(u^=lastans,x^=lastans)
1 u x????????? 把u節(jié)點的權值改成x。(u^=lastans,x^=lastans)
2 u x????????? 添加一個編號為"當前樹中節(jié)點數+1"的節(jié)點,其父節(jié)點為u,其權值為x。(u^=lastans,x^=lastans)
最開始時lastans=0。
Input
輸入第一行包括一個正整數n(1<=n<=30000),代表樹上的初始節(jié)點數。
接下來n-1行,每行2個整數u,v,為樹上的一條無向邊。
任何時刻,樹上的任何權值大于等于0,且兩兩不同。
接下來1行,包括n個整數wi,表示初始時每個節(jié)點的權值。
接下來1行,包括1個整數m(1<=m<=30000),表示操作總數。
接下來m行,每行包括三個整數 op,u,v:
op,u,v的含義見題目描述。
保證題目涉及的所有數在int內。
Output
對每個op=0,輸出一行,包括一個整數,意義見題目描述。
Sample Input
21 2
10 20
1
0 1 5
Sample Output
2HINT
Source
By Autumn
分析:
這個SIZE值要注意,由于有二分操作,所以大小定為2.0*sqrt(n)*log2(n)比較好,而不是sqrt(n),證明略。
加點的時候,分兩種情況討論,
1.如果x節(jié)點所在塊的數量還沒有達到最大值,那就把y節(jié)點加進去,然后對整個序列快排。
2.如果達到了最大的值,就新建一個塊。
最后詢問的時候,由于每一次操作之后塊里存的數組都是有序的,因此查找只需要二分。
寫兩個遞歸的query函數,在不整的塊中暴力查找,在整的塊中二分查找
g:存儲樹的形態(tài)
block:儲存屬于root的子樹,且超過SIZE,另行分塊的節(jié)點
g.del[i]:i邊是否已重復,保證塊外往塊內轉移不會出錯?
然后看代碼
luogu's #1&&cogs's #1&&bzoj's #3 (id:bbsh)
?
#include<cstdio> #include<cmath> #include<vector> #include<algorithm> using namespace std; inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f; } const int N=6e4+5,M=N<<1; int n,m,last,size[N],sum,SIZE,w[N],top[N]; struct node{int v[M],next[M],head[M],tot;bool del[M];inline void add(int x,int y){v[++tot]=y;next[tot]=head[x];head[x]=tot;} }g,block,linked; vector<int>list[N]; inline void init(int u,int f){int root=top[u];list[root].push_back(w[u]);for(int i=g.head[u];i;i=g.next[i]){if(g.v[i]==f){g.del[i]=1;continue;} if(size[root]<SIZE)size[root]++,top[g.v[i]]=root;elseblock.add(root,g.v[i]);init(g.v[i],u);} } inline void query_block(int u,int x){sum+=list[u].end()-upper_bound(list[u].begin(),list[u].end(),x);for(int i=block.head[u];i;i=block.next[i])query_block(block.v[i],x); } inline void query_out_board(int u,int x){if(w[u]>x) sum++;for(int i=g.head[u];i;i=g.next[i]){if(g.del[i]) continue; if(top[u]==top[g.v[i]])query_out_board(g.v[i],x);elsequery_block(g.v[i],x);} } int main(){#ifndef online_judgefreopen("gtygirltree.in","r",stdin);freopen("gtygirltree.out","w",stdout);#endifn=read();SIZE=(int)ceil(2.0*sqrt(n)*log2(n));for(int i=1,x,y;i<n;i++){x=read();y=read();g.add(x,y);g.add(y,x);}for(int i=1;i<=n;i++) w[i]=read(),top[i]=i,size[i]=1;init(1,0);for(int i=1;i<=n;i++) if(top[i]==i) sort(list[i].begin(),list[i].end());m=read(),last=0;for(int opt,u,x,tp;m--;){opt=read();u=read()^last;x=read()^last;if(!opt){sum=0;if(u==top[u])query_block(u,x);elsequery_out_board(u,x);printf("%d\n",last=sum);}else if(opt==1){tp=top[u];list[tp].erase(lower_bound(list[tp].begin(),list[tp].end(),w[u]));list[tp].insert(lower_bound(list[tp].begin(),list[tp].end(),x),x);w[u]=x;}else{w[++n]=x;tp=top[u];g.add(u,n);if(size[tp]<SIZE){top[n]=tp;size[tp]++;list[tp].insert(lower_bound(list[tp].begin(),list[tp].end(),x),x);}else{top[n]=n;size[u]=1;list[n].push_back(x);block.add(tp,n);}}}return 0; }?
轉載于:https://www.cnblogs.com/shenben/p/6369034.html
總結
以上是生活随笔為你收集整理的3720: Gty的妹子树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PostgreSQL GIN multi
- 下一篇: Git基础-获取仓库、提交、查看历史、撤