線段樹(dfs序建樹加區間更新和單點查詢)
阿新 • • 發佈:2019-02-06
記錄一下這道折磨了我一天的題,。。。。
具體思路: 具體關係可通過dfs序建樹,但是注意,在更新以及查詢時的數和你dfs序建成的數是不一樣的。因為你dfs序建成的樹每個左右區間以及端點會發生不符合建樹的條件。但是具體區間的更新還是可以通過新的樹進行更新的,但是下屬關係還是符合線段樹的規則的,區間越大,也就是管理的人越多,也就是端點越往上。
AC程式碼;
#include<iostream> #include<string> #include<cstring> #include<iomanip> #include<map> #include<cmath> #include<algorithm> #include<queue> #include<stack> #include<set> #include<vector> #include<stdio.h> using namespace std; # define inf 0x3f3f3f3f # define maxn 500000+100 # define ll long long # define lson l,m,rt<<1 # define rson m+1,r,rt<<1|1 vector<int>wakaka[maxn]; int vis[maxn]; int st[maxn]; int ed[maxn]; bool cover[maxn]; int ans; int num; int a[maxn]; void init() { memset(cover,0,sizeof(a)); memset(vis,0,sizeof(vis)); memset(st,0,sizeof(st)); memset(ed,0,sizeof(ed)); num=0; } void cal(int rt,int l,int r) { if(a[rt]==-1||l==r)return ;//必須先判斷a[rt]是不是-1,如果是-1.則不能往下更新。 a[rt<<1]=a[rt<<1|1]=a[rt]; a[rt]=-1; } void dfs(int u) { st[u]=++num; int len=wakaka[u].size(); for(int i=0; i<len; i++) { dfs(wakaka[u][i]); } ed[u]=num; } int query(int p,int l,int r,int rt) { if(l==r)//單點查詢 { return a[rt]; } cal(rt,l,r); int m=(l+r)>>1; if(p<=m)query(p,lson); else if(p>m)query(p,rson); } void update(int col,int L,int R,int l,int r,int rt) { if(L<=l&&R>=r) { a[rt]=col; return ; } cal(rt,l,r); int m=(l+r)>>1; if(L<=m)update(col,L,R,lson); if(R>m)update(col,L,R,rson); } int main() { int T; scanf("%d",&T); int t=0; while(T--) { int n,u,v; scanf("%d",&n); init(); for(int i=1; i<=n; i++){ wakaka[i].clear(); } memset(a,-1,sizeof(a)); for(int i=1; i<n; i++) { scanf("%d%d",&u,&v); wakaka[v].push_back(u); vis[u]=1; } for(int i=1; i<=n; i++) { if(!vis[i]) { dfs(i); break; } } int m1; scanf("%d",&m1); char str[10]; int t1,t2; printf("Case #%d:\n",++t); while(m1--) { scanf("%s",str); if(str[0]=='C') { scanf("%d",&t1); printf("%d\n",query(st[t1],1,n,1));//直接查詢單點. } else if(str[0]=='T') { scanf("%d%d",&t1,&t2); update(t2,st[t1],ed[t1],1,n,1);//更新區間。 } } } return 0; }