zoukankan      html  css  js  c++  java
  • [SDOI2011] 染色 (树链剖分)

    题目描述

    输入输出格式

    输入格式:

    输出格式:

    对于每个询问操作,输出一行答案。

    输入输出样例

    输入样例#1:

    6 5
    2 2 1 2 1 1
    1 2
    1 3
    2 4
    2 5
    2 6
    Q 3 5
    C 2 1 1
    Q 3 5
    C 5 1 2
    Q 3 5

    输出样例#1:

    3
    1
    2

    说明


    Solution

    太久没打过树剖了哈,代码能力弱的一批...

    这道题需要进行改进的地方是线段树部分.
    我们新维护两个变量:

    [ll[node],rr[node] ]

    分别用于储存当前线段树节点的左端颜色和右端颜色.
    以在查询时达到判重的作用.

    修改时也只需要注意下这两个变量即可.

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100008;
    struct sj{int to,next;}a[maxn*2];
    int x,y,z,dep[maxn],fa[maxn];
    int n,m,col[maxn],c[maxn],num;
    int head[maxn],size,id[maxn],fuck[maxn];
    int siz[maxn],zu[maxn],son[maxn];
    int ll[maxn*4],rr[maxn*4],sgm[maxn*4],lazy[maxn*4];
    void add(int x,int y)
    {
        a[++size].to=y;
        a[size].next=head[x];
        head[x]=size;
    }
    
    void dfs1(int x)
    {
        siz[x]=1;
        for(int i=head[x];i;i=a[i].next)
        {
            int tt=a[i].to;
            if(!siz[tt])
            {
                dep[tt]=dep[x]+1;
                fa[tt]=x;
                dfs1(tt);
                siz[x]+=siz[tt];
                if(siz[tt]>siz[son[x]])
                son[x]=tt;
            }
        }
    }
    
    void dfs2(int x,int anc)
    {   
        zu[x]=anc; c[++num]=col[x]; id[x]=num;
        if(son[x]) dfs2(son[x],anc);
        for(int i=head[x];i;i=a[i].next)
        {
            int tt=a[i].to;
            if(!zu[tt])
                if(tt==son[x])
                    continue;
                else dfs2(tt,tt);
        }
    }
    
    void push_down(int node)
    {
        ll[node*2]=lazy[node]; rr[node*2]=lazy[node];
        ll[node*2+1]=lazy[node]; rr[node*2+1]=lazy[node];    
        sgm[node*2]=1; sgm[node*2+1]=1;                                            
        lazy[node*2]=lazy[node]; lazy[node*2+1]=lazy[node];
        lazy[node]=0;
    }
    
    void update(int node)
    {
        ll[node]=ll[node*2]; rr[node]=rr[node*2+1];  
        sgm[node]=sgm[node*2]+sgm[node*2+1];
        if(rr[node*2]==ll[node*2+1]) sgm[node]--;
    }
    
    void build(int node,int l,int r)
    {
        if(l==r)
        {
            ll[node]=c[l];
            rr[node]=c[r];
            sgm[node]=1;
            return;
        }
    
        int mid=(l+r)/2;
        build(node*2,l,mid);
        build(node*2+1,mid+1,r);
        update(node);
        return;
    }
    
    void change(int node,int l,int r,int L,int R,int cc)
    {
        if(l>R||L>r)return;
        if(l>=L&&r<=R)
        {
            lazy[node]=cc;      
            ll[node]=lazy[node];
            rr[node]=lazy[node];
            sgm[node]=1;
            return; 
        }
    
        if(lazy[node]!=0)
        push_down(node);
        int mid=(l+r)/2;
        change(node*2,l,mid,L,R,cc);
        change(node*2+1,mid+1,r,L,R,cc);
        update(node);
    }
    
    int query(int node,int l,int r,int L,int R)
    {
        if(l>R||L>r)return 0;
        if(l>=L&&r<=R){
            return sgm[node];}
        if(lazy[node]!=0)
        push_down(node);
        int mid=(l+r)/2;
        int lll=query(node*2,l,mid,L,R);
    	int rrr=query(node*2+1,mid+1,r,L,R);
    	int ans=lll+rrr;
    	if(rr[node*2]==ll[node*2+1]&&(lll!=0&&rrr!=0))return ans-1;
    	return ans;
    }
    
    void kuai(int x,int y,int z)
    {
        while(zu[x]!=zu[y])
        {
            if(dep[zu[x]]<dep[zu[y]])
            swap(x,y);
            change(1,1,n,id[zu[x]],id[x],z);
            x=fa[zu[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        change(1,1,n,id[x],id[y],z);
    }
    
    int newww(int r,int z,int y,int p)
    {
        if (z==y) return ll[r];
        if (lazy[r]) push_down(r);
        int k=(z+y)/2;
        if (p>k) return newww(r*2+1,k+1,y,p);
        else return newww(r*2,z,k,p);
    }
    
    int check(int x,int y)
    {
        int kk=0,nx,ny;
        while (zu[x]!=zu[y]) 
    	{
            if (dep[zu[x]]>dep[zu[y]]) 
    		swap(x,y);
            kk+=query(1,1,n,id[zu[y]],id[y]);
    		nx=newww(1,1,n,id[zu[y]]);
            ny=newww(1,1,n,id[fa[zu[y]]]);
            y=fa[zu[y]];
    		if (nx==ny) kk--;
        }
        if (dep[x]>dep[y]) swap(x,y);
        kk+=query(1,1,n,id[x],id[y]);
        cout<<(kk?kk:1)<<endl;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        scanf("%d",&col[i]);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y); add(y,x);
        }
        dfs1(1);
        dfs2(1,1);
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            char ch; cin>>ch;
            if(ch=='Q')
                scanf("%d%d",&x,&y),
                check(x,y);
            else
                scanf("%d%d%d",&x,&y,&z),
                kuai(x,y,z);
        }
    }
    
  • 相关阅读:
    css笔记
    js面向对象开发之--元素拖拽
    git命令笔记
    数据扁平化笔记。
    手写冒泡排序
    ant design-Table组件实现每一行某个特定字段连续相同进行行合并。
    Array.prototype.reduce()。
    I/O多路复用
    TCP/IP四层体系结构
    TCP的三次握手和四次挥手,为什么?
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9237246.html
Copyright © 2011-2022 走看看