【BZOJ】【3083】遥远的国度

树链剖分/dfs序


  其实过了【BZOJ】【4034】【HAOI2015】T2以后就好搞了……

  链修改+子树查询+换根

  其实静态树的换根直接树链剖分就可以搞了……

  因为其实只有一样变了:子树

  如果root在x的子树中(以1为根dfs的时候),那么现在x的子树就变成了整个dfs序中,除去含有root的那个子树的剩下的部分,画个图大概就是这样:(红色部分为现在的子树)

  我们发现,这种子树由于换根而产生变化的情况,仅当在以1为根时的树中,x是new_root的祖先时发生,那么我们判断这种情况是否发生只需这样:if (start[x]<=start[root] && end[x]>=end[root]) ......

  而其他情况?则和原来一样啦~子树并没有变化,对吧~

  那么我们就可以搞了……

 

WA了几发:这题中点权的范围是0~2147483647(P.S.我一开始还以为得开unsigned int,因为写的是$\leq2^{31}$……)所以不能认为tag=0就是没有标记,而应该用-1作为空标记……

  1 /**************************************************************
  2     Problem: 3083
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:4444 ms
  7     Memory:23172 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 3083
 11 #include<cstdio>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;--i)
 19 #define pb push_back
 20 using namespace std;
 21 typedef long long LL;
 22 inline int getint(){
 23     int r=1,v=0; char ch=getchar();
 24     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
 25     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
 26     return r*v;
 27 }
 28 const int N=100010;
 29 const int INF=2147483647;
 30 /*******************template********************/
 31 int to[N<<1],next[N<<1],head[N],cnt;
 32 void add(int x,int y){
 33     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
 34     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
 35 }
 36 int t[N<<2],mn[N<<2];
 37 //t[o]表示set标记
 38 #define mid (l+r>>1)
 39 #define L (o<<1)
 40 #define R (o<<1|1)
 41 void Push_down(int o,int l,int r){
 42     if (t[o]!=-1){
 43         mn[L]=mn[R]=t[L]=t[R]=t[o];
 44         t[o]=-1;
 45     }
 46 }
 47 void maintain(int o,int l,int r){
 48     mn[o]=min(mn[L],mn[R]);
 49 }
 50 void update(int o,int l,int r,int ql,int qr,int v){
 51     if (ql<=l && qr>=r) t[o]=mn[o]=v;
 52     else{
 53         Push_down(o,l,r);
 54         if (ql<=mid) update(L,l,mid,ql,qr,v);
 55         if (qr>mid) update(R,mid+1,r,ql,qr,v);
 56         maintain(o,l,r);
 57     }
 58 }
 59 int query(int o,int l,int r,int ql,int qr){
 60     if (ql>qr) return INF;
 61     if (ql<=l && qr>=r) return mn[o];
 62     else{
 63         int ans=INF;
 64         Push_down(o,l,r);
 65         if (ql<=mid) ans=min(ans,query(L,l,mid,ql,qr));
 66         if (qr>mid) ans=min(ans,query(R,mid+1,r,ql,qr));
 67         return ans;
 68     }
 69 }
 70 int n,m,rt;
 71 int a[N];
 72 int fa[N][20],st[N],ed[N],son[N],dep[N],size[N],top[N],tot;
 73 void dfs(int x){
 74     size[x]=1; son[x]=0;
 75     F(i,1,17)
 76         if (dep[x]>=(1<<i)) fa[x][i]=fa[fa[x][i-1]][i-1];
 77         else break;
 78     int mx=0;
 79     for(int i=head[x];i;i=next[i])
 80         if (to[i]!=fa[x][0]){
 81             fa[to[i]][0]=x;
 82             dep[to[i]]=dep[x]+1;
 83             dfs(to[i]);
 84             size[x]+=size[to[i]];
 85             if (size[to[i]]>mx) son[x]=to[i],mx=size[to[i]];
 86         }
 87 }
 88 bool vis[N];
 89 void connect(int x,int f){
 90     vis[x]=1; top[x]=f;
 91     st[x]=++tot;
 92     if (son[x]) connect(son[x],f);
 93  
 94     for(int i=head[x];i;i=next[i])
 95         if (!vis[to[i]])
 96             connect(to[i],to[i]);
 97     ed[x]=tot;
 98 }
 99 void modify(int x,int y,int v){
100     while(top[x]!=top[y]){
101         if (dep[top[x]]<dep[top[y]]) swap(x,y);
102         update(1,1,n,st[top[x]],st[x],v);
103         x=fa[top[x]][0];
104     }
105     if (dep[x]>dep[y]) swap(x,y);
106     update(1,1,n,st[x],st[y],v);
107 }
108  
109 int main(){
110 #ifndef ONLINE_JUDGE
111     freopen("3083.in","r",stdin);
112 //  freopen("3083.out","w",stdout);
113 #endif
114     n=getint(); m=getint();
115     F(i,2,n){
116         int x=getint(),y=getint();
117         add(x,y);
118     }
119     dfs(1);
120     connect(1,1);
121     memset(t,-1,sizeof t);
122     F(i,1,n){
123         a[i]=getint();
124         update(1,1,n,st[i],st[i],a[i]);
125     }
126     rt=getint();
127     F(i,1,m){
128         int cmd=getint();
129         if (cmd==1){
130             rt=getint();
131         }else if (cmd==2){
132             int x=getint(),y=getint();
133             int v=getint();
134             modify(x,y,v);
135         }else if (cmd==3){
136             int x=getint();
137             if (st[rt]>=st[x] && ed[rt]<=ed[x]){
138                 int y=rt,t=dep[rt]-dep[x]-1,ans=INF;
139                 D(i,17,0) if (t&(1<<i)) y=fa[y][i];
140                 if (1<=st[y]-1) ans=min(ans,query(1,1,n,1,st[y]-1));
141                 if (n>=ed[y]+1) ans=min(ans,query(1,1,n,ed[y]+1,n));
142                 printf("%d\n",ans);
143             }else{
144                 printf("%d\n",query(1,1,n,st[x],ed[x]));
145             }
146         }
147     }
148     return 0;
149 }
View Code

3083: 遥远的国度

Time Limit: 10 Sec  Memory Limit: 1280 MB
Submit: 1370  Solved: 335
[Submit][Status][Discuss]

Description

描述
zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成 了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有 一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的 话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但 zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

Input

第1行两个整数n m,代表城市个数和操作数。
第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
第n+1行,有n个整数,代表所有点的初始防御值。
第n+2行一个整数 id,代表初始的首都为id。
第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数 p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。

Output


对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

Sample Input

3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1

Sample Output

1
2
3
4
提示
对于20%的数据,n<=1000 m<=1000。
对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。

HINT

Source

[Submit][Status][Discuss]
posted @ 2015-05-13 20:32  Tunix  阅读(308)  评论(0编辑  收藏  举报