bzoj 3720: 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
21 2
10 20
1
0 1 5
Sample Output
2HINT
Source
By Autumn
傳說中的樹分塊。。。
將樹分塊,如果父親節點所在的塊已經滿了,就新建一個塊,否則加入父親節點所在的塊;插入節點類似
同時在塊中維護一個有序表,如果遇見整塊就可以直接查詢;
至於查詢的話,直接dfs,如果碰到了與根節點同一個塊的點就暴力統計(因為該塊不一定全在根節點子樹內),否則就直接統計整個塊(易知該塊子樹包含在詢問子樹裏面)
細節有點多。。。
// MADE BY QT666 #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> #include<vector> using namespace std; typedef long long ll; const int N=100050; int gi() { int x=0,flag=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) flag=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x*flag; } struct Block{ int a[210],size; void insert(int x){ size++;int i; for(i=size;i>1&&a[i-1]>x;i--) a[i]=a[i-1]; a[i]=x; } void update(int x,int y){ int pl=lower_bound(a+1,a+1+size,x)-a; for(;pl<size&&a[pl+1]<y;pl++) a[pl]=a[pl+1]; for(;pl>1&&a[pl-1]>y;pl--) a[pl]=a[pl-1]; a[pl]=y; } int query(int x){ int pl=upper_bound(a+1,a+1+size,x)-a; return size-pl+1; } }block[N]; int cnt,w[N],head[N],to[N],nxt[N],n,m,pos[N],tot,sz,ans,f[N]; vector<int>p[N]; void lnk(int x,int y){ to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt; to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt; } void build(int x,int fa){ f[x]=fa; if(block[pos[fa]].size==sz){ tot++;block[tot].insert(w[x]); pos[x]=tot;p[pos[fa]].push_back(tot); } else block[pos[fa]].insert(w[x]),pos[x]=pos[fa]; for(int i=head[x];i;i=nxt[i]){ int y=to[i]; if(y!=fa) build(y,x); } } void dfs_block(int x,int val){ ans+=block[x].query(val); for(int i=0;i<p[x].size();i++) dfs_block(p[x][i],val); } void dfs(int x,int val){ if(w[x]>val) ans++; for(int i=head[x];i;i=nxt[i]){ int y=to[i]; if(y!=f[x]){ if(pos[y]==pos[x]) dfs(y,val); else dfs_block(pos[y],val); } } } int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); n=gi(); for(int i=1;i<n;i++){ int x=gi(),y=gi();lnk(x,y); } for(int i=1;i<=n;i++) w[i]=gi(); sz=sqrt(n)+1;build(1,0); m=gi();ans=0; for(int i=1;i<=m;i++){ int flag=gi(),u=gi(),v=gi(); u^=ans,v^=ans; if(flag==0){ ans=0;dfs(u,v); printf("%d\n",ans); } if(flag==1){ block[pos[u]].update(w[u],v); w[u]=v; } if(flag==2){ n++;w[n]=v;f[n]=u;lnk(u,n); if(block[pos[u]].size==sz){ tot++;block[tot].insert(w[n]); pos[n]=tot;p[pos[u]].push_back(tot); } else block[pos[u]].insert(w[n]),pos[n]=pos[u]; } } return 0; }
bzoj 3720: Gty的妹子樹