您的位置:首页 > 其它

ZOJ 3686 A Simple Tree Problem

2013-04-11 09:53 155 查看
ZOJ月赛,题目描述确实很simple。。。

那么就是把一棵树转换为线性表,使得整个子树都在一个区间里。。

方法就是前序遍历了,遍历完一颗树它的根节点都连续的存在它后面了。

对于每一个节点要存它和它子树所在区间,

l显然是该节点的值,r就是它最后一个子节点的r,dfs的时候返回就可以了。

对于叶子节点来说,r就是它本身,可以把返回的值初始化为l,这样就不用判断是否为叶子了。

其次就是说区间的xor问题。。由于是求1的个数,那么就是求sum值了。

对于一个区间,如果xor了,等价于sum=r-l+1-sum。

另外就是困扰我多时的pushdown问题。。。

由于是跟not only success学的,而他那里面都是代码,没有教程,所以pushdown很弱。。。

现在大致是明白了懒惰标记跟本节点无关,pushdown的时候处理本节点的懒惰标记、子节点的懒惰标记和sum值。

而update到了符合条件的区间的时候,需要处理本节点的sum值和懒惰标记

而que的时候就不用了。。。。

实在不明白在知道这些事情之前,自己怎么ac的题的。。。大致都跟not only success代码对照过才交的。。。完全没有技术含量。。

#include<cstdio>
#include<vector>
#include<iostream>
#define X 100010
using namespace std;

vector<int>e[X];
int hl[X],hr[X],top;
int dfs(int u){
int x,v,i,n;
n=e[u].size();
hl[u]=top;x=top++;
for(i=0;i<n;i++){
v=e[u][i];
x=dfs(v);
}
hr[u]=x;
return x;
}

#define lson l,mid,rt*2
#define rson mid+1,r,rt*2+1
int sum[X*4],a[X*4],ll,rr,c;
void pushup(int rt){
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void pushdown(int l,int r,int rt){
if(a[rt]){
a[rt*2]^=1;a[rt*2+1]^=1;a[rt]=0;
int mid=l+r>>1;
sum[rt*2]=(mid-l+1)-sum[rt*2];
sum[rt*2+1]=(r-mid)-sum[rt*2+1];
}
}
void update(int l,int r,int rt){
if(ll<=l&&rr>=r){
a[rt]^=1;
sum[rt]=r-l+1-sum[rt];
return ;
}
pushdown(l,r,rt);
int mid=l+r>>1;
if(ll<=mid)update(lson);
if(rr> mid)update(rson);
pushup(rt);
}
int que(int l,int r,int rt){
if(ll<=l&&rr>=r){
return sum[rt];
}
pushdown(l,r,rt);
int as=0;
int mid=l+r>>1;
if(ll<=mid)as=que(lson);
if(rr>mid)as+=que(rson);
return as;
}
int main(){
int i,j,u,v,n,m;
char str[5];
while(~scanf("%d%d",&n,&m)){
for(i=1;i<=n;i++){
hl[i]=hr[i]=0;
e[i].clear();
}
for(i=2;i<=n;i++){
scanf("%d",&j);
e[j].push_back(i);
}
top=1;dfs(1);

for(i=0;i<top*4;i++)a[i]=sum[i]=0;
while(m--){
scanf("%s%d",str,&i);
ll=hl[i];rr=hr[i];
if(str[0]=='o')update(1,top,1);
else printf("%d\n",que(1,top,1));
}
puts("");
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: