hdu3974(dfs序建線段樹)
阿新 • • 發佈:2019-01-02
題意:給出一個有向樹,初始所有節點為-1.有兩種操作,一種為(T,x,y),表示將x節點的所有子樹中的節點變為y,另一種為(C,x),為求x節點的值
程式碼:
#include <queue> #include <math.h> #include <vector> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int siz=50005; int tree[siz<<3]; void build(int l,int r,int rt){ tree[rt]=-1; if(l==r) return; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } void pushdown(int rt){ if(tree[rt]!=-1){ tree[rt<<1]=tree[rt]; tree[rt<<1|1]=tree[rt]; tree[rt]=-1; } } void Change(int L,int R,int p,int l,int r,int rt){ if(L<=l&&r<=R){ tree[rt]=p; return; } pushdown(rt); int m=(l+r)>>1; if(L<=m) Change(L,R,p,l,m,rt<<1); if(R>m) Change(L,R,p,m+1,r,rt<<1|1); } int query(int p,int l,int r,int rt){ if(l==r) return tree[rt]; pushdown(rt); int m=(l+r)>>1; if(p<=m) query(p,l,m,rt<<1); else query(p,m+1,r,rt<<1|1); } vector<int> G[siz]; int ll[siz],rr[siz],vis[siz]; void dfs(int s,int &id){ int i,tmp; ll[s]=id++; for(i=0;i<G[s].size();i++){ tmp=G[s][i]; dfs(tmp,id); } rr[s]=id++; } int main(){ char ch; int t,n,m,u,v,i,id,cas=1; scanf("%d",&t); while(t--){ //用dfs序建樹,直接就轉換為 scanf("%d",&n); //線段樹區間更新,單點查詢 build(1,2*n,1); for(i=1;i<=n;i++) vis[i]=0,G[i].clear(); for(i=1;i<n;i++){ scanf("%d%d",&u,&v); G[v].push_back(u); vis[u]=1; } memset(ll,-1,sizeof(ll)); memset(rr,-1,sizeof(rr)); id=1; for(i=1;i<=n;i++) //有向樹找根節點 if(vis[i]==0) dfs(i,id); scanf("%d",&m); printf("Case #%d:\n",cas++); while(m--){ cin>>ch; if(ch=='C'){ scanf("%d",&u); printf("%d\n",query(ll[u],1,2*n,1)); } else{ scanf("%d%d",&u,&v); //每次更新只要在第一次出現改點的dfs序 Change(ll[u],rr[u],v,1,2*n,1); //和最後一次出現改點的dfs序之間區間更新即可 } } } return 0; }