给一颗树,结点有权值,更新子树所有结点,查询结点子树的和;
思路参考我
转换完之后就是区间更新和查询,然后更新sum就是把开关的房间调换一下; 更新add值就用对2取余,不能用异或~~(刚开始想着用异或1,后来发现,add的值会超过1) 代码(
注意main() 函数里 A[L[i]]=a; 调试了无数次才发现是这里的问题)
因为把结点按照DFS序重新编号后,L[i]才是线段树维护序列的下标;
#include#include #include #include #define mem(x) memset(x,0,sizeof(x))#define ls l,m,rt<<1#define rs m+1,r,rt<<1|1using namespace std;const int N=200010;vector G[N];int sum[N<<2],L[N],R[N],A[N],add[N<<2];int fa[N];int vv=0;void init(int n){ for(int i=1;i ";for(int i=1;i<=7;i++)cout< <<' ';cout< >1; build(ls);build(rs); pu(rt);}void update(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { sum[rt]=(r-l+1)-sum[rt]; add[rt]=(add[rt]+1)%2; return ; } int m=(l+r)>>1; pd(rt,m-l+1,r-m); if(L<=m)update(L,R,ls); if(R>m)update(L,R,rs); pu(rt);}int query(int L,int R,int l,int r,int rt){ //cout<<"add-->";for(int i=1;i<=20;i++)cout< <<' ';cout< ";for(int i=1;i<=20;i++)cout< <<' ';cout< >1; pd(rt,m-l+1,r-m); int ans=0; if(L<=m)ans+=query(L,R,ls); if(R>m)ans+=query(L,R,rs); pu(rt); return ans;}int main(){ int n,m; while(~scanf("%d",&n)) { int a; init(n); for(int i=2;i<=n;i++) { scanf("%d",&a); fa[i]=a; //G[i].push_back(a); G[a].push_back(i); } dfs(1); for(int i=1;i<=n;i++) { scanf("%d",&a); A[L[i]]=a; } //cout<<"L[2]="< <<' '<<"R[2]"< <