• CF877E Danil and a Part-time Job 线段树维护dfs序


    (color{#0066ff}{题目描述})

    有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0
    共有 m 次操作,操作分为两种

    get 询问一个点 x 的子树里有多少个 1
    pow 将一个点 x 的子树中所有节点取反

    对于每个 get 给出答案

    (color{#0066ff}{输入格式})

    第一行一个整数 n
    第二行共 n−1 个整数,第 i 个数 (x_i) 表示 (x_i) 是 i+1 的父亲,
    第三行给出每个点的初始权值
    第四行一个整数 m
    接下来 m 行为操作类型和位置

    (color{#0066ff}{输出格式})

    对于每个 get 给出答案

    (color{#0066ff}{输入样例})

    4
    1 1 1
    1 0 0 1
    9
    get 1
    get 2
    get 3
    get 4
    pow 1
    get 1
    get 2
    get 3
    get 4
    

    (color{#0066ff}{输出样例})

    2
    0
    0
    1
    2
    1
    1
    0
    

    (color{#0066ff}{数据范围与提示})

    (1leq n leq 200000,1leq qleq 200000)

    (color{#0066ff}{题解})

    线段树维护dfs序

    同一子树内dfs序连续

    线段树上修改查询即可

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define _ 0
    #define LL long long
    #ifndef olinr
    inline char getc()
    {
    	static char buf[100001],*p1=buf,*p2=buf;
    	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100001,stdin),p1==p2)? EOF:*p1++;
    }
    #else
    #define getc() getchar()
    #endif
    inline LL in()
    {
    	LL x=0,f=1; char ch;
    	while(!isdigit(ch=getc()))(ch=='-')&&(f=-f);
    	while(isdigit(ch)) x=x*10+(ch^48),ch=getc();
    	return x*f;
    }
    const int max=205005;
    int val[max],dfn[max],redfn[max],siz[max];
    class SGT
    {
        private:
            struct node
            {
                int l,r;
    			int val;
    			node* ch[2];
    			bool tag;
    			node(int l,int r,int val,int tag):l(l),r(r),val(val),tag(tag){}
    			void upd() {val=ch[0]->val+ch[1]->val;}
    			int mid() {return (l+r)>>1;}
    			int siz() {return r-l+1;}
    			void dwn()
    			{
    				if(!tag) return;
    				ch[0]->val=ch[0]->siz()-ch[0]->val;
    				ch[1]->val=ch[1]->siz()-ch[1]->val;
    				ch[0]->tag^=1;
    				ch[1]->tag^=1;
    				tag=0;
    			}
            };
    		typedef node* nod;
    	public:
    		nod root;
    		void build(nod &o,int l,int r)
    		{
    			o=new node(l,r,0,0);
    			if(l==r) return (void)(o->val=val[redfn[l]]);
    			build(o->ch[0],l,o->mid());
    			build(o->ch[1],o->mid()+1,r);
    			o->upd();
    		}
    		void lazy(nod o,int l,int r)
    		{
    			if(o->r<l||o->l>r) return;
    			if(l<=o->l&&o->r<=r) 
    			{
    				o->tag^=1;
    				o->val=o->siz()-o->val;
    				return;
    			} 
    			o->dwn();
    			lazy(o->ch[0],l,r),lazy(o->ch[1],l,r);
    			o->upd();
    		}
    		int query(nod o,int l,int r)
    		{
    			if(o->r<l||o->l>r) return 0;
    			if(l<=o->l&&o->r<=r) return o->val;
    			o->dwn();
    			return query(o->ch[0],l,r)+query(o->ch[1],l,r);
    		}
    }s;
    struct node
    {
    	int to;
    	node *nxt;
    	node(int to,node *nxt):to(to),nxt(nxt){}
    };
    typedef node* nod;
    nod head[max];
    int cnt;
    void add(int from,int to)
    {
    	nod t=new node(to,head[from]);
    	head[from]=t;
    }
    void dfs(int x,int f)
    {
    	siz[x]=1;
    	dfn[x]=++cnt;
    	redfn[cnt]=x;
    	for(nod i=head[x];i;i=i->nxt)
    		if(i->to!=f) dfs(i->to,x),siz[x]+=siz[i->to];
    }
    int n,m;
    
    int main()
    {	
    	n=in(); int x;
    	for(int i=1;i<=n-1;i++) x=in(),add(x,i+1),add(i+1,x);
    	for(int i=1;i<=n;i++) val[i]=in();
    	dfs(1,0);
    	s.build(s.root,1,n);
    	m=in();
    	char ch;
    	while(m--)
    	{
    		while(!isalpha(ch=getc()));
    		x=in();
    		if(ch=='g') printf("%d
    ",s.query(s.root,dfn[x],dfn[x]+siz[x]-1));
    		else s.lazy(s.root,dfn[x],dfn[x]+siz[x]-1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    临摹帖
    PC+PLC通过Modbus协议构建工控系统
    mvn打包时出现一个子模块找不到另一个子模块的情况
    T-SQL——函数——字符串操作函数
    T-SQL——透视PIVOT动态获取待扩展元素集
    T-SQL——数据透视和逆透视
    T-SQL——关于表数据的复制插入
    T-SQL——关于SQL读取Excel文件
    T-SQL——关于SqlPrompt的使用
    微信小程序--聊天室小程序(云开发)
  • 原文地址:https://www.cnblogs.com/olinr/p/10081036.html
Copyright © 2020-2023  润新知