码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3631

时间:2015-08-10 19:27:06      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:

裸的链剖

技术分享
  1 #include<bits/stdc++.h>
  2 #define lowbit(a) ((a)&(-(a)))
  3 #define l(a) ((a)<<1)
  4 #define r(a) ((a)<<1|1)
  5 #define clr(a,x) memset(a,x,sizeof(a))
  6 #define rep(i,l,r) for(int i=l;i<(r);i++)
  7 #define Rep(i,a) rep(i,0,e[a].size())
  8 typedef long long ll;
  9 using namespace std;
 10 int read()
 11 {
 12     char c=getchar();
 13     int ans=0,f=1;
 14     while(!isdigit(c)){
 15         if(c==-) f=-1;
 16         c=getchar();
 17     }
 18     while(isdigit(c)){
 19         ans=ans*10+c-0;
 20         c=getchar();
 21     }
 22     return ans*f;
 23 }
 24 struct node{
 25     int l,r,sum,add;
 26 };
 27 const int maxn=300009,inf=0x7fffffff;
 28 int n,dfstime=0,a[maxn],w[maxn],dep[maxn],size[maxn],f[maxn],son[maxn],top[maxn],id[maxn],idr[maxn];
 29 node x[maxn<<2];
 30 vector<int>e[maxn];
 31 void dfs(int k){
 32     size[k]=1;
 33     Rep(i,k){
 34         int to=e[k][i];
 35         if(f[k]==to) continue;
 36         f[to]=k;
 37         dep[to]=dep[k]+1;
 38         dfs(to);
 39         size[k]+=size[to];
 40         if(!son[k]||size[son[k]]<size[to]) son[k]=to;
 41     }
 42 }
 43 int Top;
 44 void Dfs(int k){
 45     top[k]=Top;
 46     id[k]=++dfstime;
 47     idr[id[k]]=k;
 48     if(son[k]) Dfs(son[k]);
 49     Rep(i,k){
 50         int to=e[k][i];
 51         if(!id[to]) Dfs(Top=to);
 52     }
 53 }
 54 void maintain(int k){
 55     x[k].sum=x[l(k)].sum+x[r(k)].sum;
 56 }
 57 void pushdown(int k){
 58     if(x[k].l!=x[k].r&&x[k].add){
 59         x[l(k)].add+=x[k].add;
 60         x[r(k)].add+=x[k].add;
 61         x[l(k)].sum+=(x[l(k)].r-x[l(k)].l+1)*x[k].add;
 62         x[r(k)].sum+=(x[r(k)].r-x[r(k)].l+1)*x[k].add;
 63     }
 64     x[k].add=0;
 65 }
 66 void modify(int k,int l,int r,int t){
 67     //cout<<k<<‘ ‘<<l<<‘ ‘<<r<<endl;
 68     pushdown(k);
 69     if(x[k].l==l&&x[k].r==r){
 70         x[k].add+=t;
 71         x[k].sum+=(r-l+1)*t;
 72         return;
 73     }
 74     int mid=(x[k].l+x[k].r)>>1;
 75     if(l>mid) modify(r(k),l,r,t);
 76     else if(r<=mid) modify(l(k),l,r,t);
 77     else{
 78         modify(l(k),l,mid,t);
 79         modify(r(k),mid+1,r,t);
 80     }
 81     maintain(k);
 82 }
 83 int sum(int k,int u){
 84     pushdown(k);
 85     if(x[k].l==x[k].r) return x[k].sum;
 86     int mid=(x[k].l+x[k].r)>>1;
 87     return sum(u<=mid?l(k):r(k),u);
 88 }
 89 void build(int k,int l,int r){
 90     x[k].l=l,x[k].r=r,x[k].add=0;
 91     if(l==r){
 92         x[k].sum=0;
 93         return;
 94     }
 95     int mid=(l+r)>>1;
 96     build(l(k),l,mid);
 97     build(r(k),mid+1,r);
 98     maintain(k);
 99 }
100 void init(){
101     dfs(1);
102     Dfs(Top=1);
103     build(1,1,n);
104     //cout<<"init ok\n";
105     //rep(i,1,n<<1|1){
106     //    printf("%d %d %d %d\n",i,x[i].l,x[i].r,x[i].sum);
107     //}
108 }
109 void add(int u,int v,int t){
110     //cout<<"u&v:"<<u<<‘ ‘<<v<<endl;
111     while(top[u]!=top[v]){
112         if(dep[top[u]]<dep[top[v]]) swap(u,v);
113         modify(1,id[top[u]],id[u],t);
114         u=f[top[u]];
115     }
116     if(dep[u]>dep[v]) swap(u,v);
117     modify(1,id[u],id[v],t);
118 }
119 int main()
120 {    
121     n=read();
122     rep(i,1,n+1) a[i]=read();
123     rep(i,1,n){
124         int from=read(),to=read();
125         e[from].push_back(to);
126         e[to].push_back(from);
127     }
128     init();
129     add(a[1],a[1],1);
130     rep(i,1,n){
131         add(a[i],a[i+1],1);
132         add(a[i],a[i],-1);
133     }
134     add(a[n],a[n],-1);
135     rep(i,1,n+1){
136         printf("%d\n",sum(1,id[i]));
137     }
138     return 0;
139 }
View Code

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 856  Solved: 413
[Submit][Status][Discuss]

Description

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

Input

第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

Output

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。

Sample Input

5
1 4 5 3 2
1 2
2 4
2 3
4 5

Sample Output

1
2
1
2
1

HINT

 

2<= n <=300000

 

Source

 
[Submit][Status][Discuss]

bzoj3631

标签:

原文地址:http://www.cnblogs.com/chensiang/p/4718724.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!