3974 DFS序+線段樹區間更新/查詢
阿新 • • 發佈:2018-12-21
題意
一個公司有n個人,有一個人是領導(等級最高)沒有上司,其餘每個人都有一個上司。
給定m個要求,當輸入為“C x”時,輸出x當前的任務;當輸入為"T x y"時,給x分配一個任務y(此時,x和x的下屬都需要放棄原來的任務,執行當前的任務y)。
思路
dfs序+區間更新
#include<cstdio> #include<cstring> using namespace std; const int maxn=131072; int in[maxn/2],out[maxn/2],sum[maxn]; int head[maxn],pre[maxn/2]; int time,cnt,root; struct node { int to,next; }e[maxn]; void add(int u,int v) { e[cnt]=node{v,head[u]}; head[u]=cnt++; } void dfs(int x,int fa) { in[x]=++time; for(int i=head[x];i!=-1;i=e[i].next) { int a=e[i].to; if(e[i].to==fa) continue; dfs(a,x); } out[x]=time; } void pushup(int rt) { if(sum[rt]!=-1) //有任務時才更新 { sum[rt<<1]=sum[rt<<1|1]=sum[rt]; sum[rt]=-1; } } void build(int l,int r,int rt) { sum[rt]=-1; if(l==r) return ; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l && R>=r) { sum[rt]=c; //分配任務 return ; } pushup(rt); int m=(l+r)>>1; if(L<=m) update(L,R,c,l,m,rt<<1); if(R>m) update(L,R,c,m+1,r,rt<<1|1); } int query(int L,int l,int r,int rt) { if(l==r) return sum[rt]; pushup(rt); int m=(l+r)>>1; int ans; if(L<=m) ans=query(L,l,m,rt<<1); else ans=query(L,m+1,r,rt<<1|1); return ans; } int main() { int t,n,m; scanf("%d",&t); for(int k=1;k<=t;k++) { time=cnt=0; memset(head,-1,sizeof(head)); int x,y; scanf("%d",&n); for(int i=1;i<=n;i++) pre[i]=i; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); pre[x]=y; add(y,x); if(pre[y]==y) //找出領導(根節點) root=y; } dfs(root,-1); build(1,n,1); printf("Case #%d:\n",k); scanf("%d",&m); char s; for(int i=1;i<=m;i++) { scanf(" %c",&s); if(s=='C') { scanf("%d",&x); printf("%d\n",query(in[x],1,n,1)); } else { scanf("%d%d",&x,&y); update(in[x],out[x],y,1,n,1); } } } return 0; }
一開始理解的並不好,寫的程式比較亂,雖然提交過了,但再次檢視時發現有許多沒有用的程式碼。還是需要好好理解線段樹。。。