bzoj2243: [SDOI2011]染色 树链剖分

44 篇文章 0 订阅
37 篇文章 0 订阅
熟练度很重要,一次AC~~~。
/**************************************************************
    Problem: 2243
    User: xujiahe
    Language: C++
    Result: Accepted
    Time:6748 ms
    Memory:20908 kb
****************************************************************/
 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define maxn 200000
#define ll long long
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define  ss printf("orz\n")
int fa[maxn],siz[maxn],top[maxn],w[maxn],son[maxn],dep[maxn],id,lc,rc;
struct node
{
    int u,v,next;
}g[maxn];
int num,n,first[maxn],val[maxn];
int tree[maxn<<1],col[maxn<<1],lcol[maxn<<1],rcol[maxn<<1];
void build(int a,int b)
{
    num++;
    g[num].v=b;
    g[num].next=first[a];
    first[a]=num;
}
void dfs(int now)
{
    int v,ceng;
    int maxv=0,flag=0;
    siz[now]=1;
    for(int i=first[now];i;i=g[i].next)
    {
        v=g[i].v;
        if(v==fa[now]) continue;
        dep[v]=dep[now]+1;
        fa[v]=now;
        dfs(v);
        siz[now]+=siz[v];
        if(siz[v]>maxv)
        {
            maxv=siz[v];
            flag=v;
        }
    }
    son[now]=flag;
}
void getid(int now,int root)
{
    w[now]=++id;
    top[now]=root;
    if(son[now]) getid(son[now],top[now]);
    for(int i=first[now]; i; i=g[i].next)
    {
        if(g[i].v!=son[now]&&g[i].v!=fa[now])
        {
            getid(g[i].v,g[i].v);
        }
    }
}
void print(int rt,int l,int r)
{
    int m=(l+r)>>1;
    printf("%d %d %d\n",rt,l,r);
    printf("%d\n",col[rt]);
    printf("%d %d %d\n\n",tree[rt],lcol[rt],rcol[rt]);
    if(l==r)
    {
        return ;
    }
    print(lson);
    print(rson);
}
void pushdown(int rt)
{
    if(col[rt]!=-1)
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        lcol[rt<<1]=rcol[rt<<1]=lcol[rt<<1|1]=rcol[rt<<1|1]=col[rt];
        tree[rt<<1]=tree[rt<<1|1]=1;
        col[rt]=-1;
    }
}
void pushup(int rt)
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    lcol[rt]=lcol[rt<<1];
    rcol[rt]=rcol[rt<<1|1];
    if(rcol[rt<<1]==lcol[rt<<1|1])
        tree[rt]--;
}
void update(int rt,int l,int r,int x,int y,int add)
{
    if(x<=l&&y>=r)
    {
        tree[rt]=1;
        lcol[rt]=rcol[rt]=add;
        col[rt]=add;
        return ;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(x<=m)
    {
        update(lson,x,y,add);
    }
    if(y>m)
    {
        update(rson,x,y,add);
    }
    pushup(rt);
}
int query(int rt,int l,int r,int x,int y)
{
    if(l==x)
    {
        lc=lcol[rt];
    }
    if(r==y)
    {
        rc=rcol[rt];
    }
    if(x<=l&&y>=r)
    {
        return tree[rt];
    }
    int tmp=0;
    int t1,t2;
    t1=t2=-1;
    pushdown(rt);
    int m=(l+r)>>1;
    if(x<=m)
    {
        t1=rcol[rt<<1];
        tmp+=query(lson,x,y);
    }
    if(y>m)
    {
        t2=lcol[rt<<1|1];
        tmp+=query(rson,x,y);
    }
    if(t1==t2&&t1!=-1)
    {
        tmp--;
    }
    return tmp;
}
void getans(int x,int y,int z,int op)
{
    int f1,f2,t1,t2,t;
    t1=t2=-1;
    int ans=0;
    if(op==1)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])
            {
                swap(x,y);
                swap(t1,t2);
            }
            ans+=query(1,1,n,w[top[x]],w[x]);
            ans-= (t1== rc);
            t1 = lc;
            x=fa[top[x]];
        }
        if (dep[x] < dep[y])
        {
            swap(x,y);
            swap(t1,t2);
        }
        ans+=query(1,1,n,w[y],w[x]);
        ans -= ((t1 == rc && t1 != -1) + (t2 == lc && t2 != -1));
        printf("%d\n",ans);
        return ;
    }
    if(op==2)
    {
 
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])
            {
                swap(x,y);
            }
            update(1,1,n,w[top[x]],w[x],z);
            x=fa[top[x]];
        }
        if (dep[x] < dep[y])
        {
            swap(x,y);
        }
        update(1,1,n,w[y],w[x],z);
        return ;
    }
}
int main()
{
    char str[20];
    int a,b,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&val[i]);
    }
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        build(a,b);
        build(b,a);
    }
    dfs(1);
    getid(1,1);
    int x,y,z;
    memset(col,-1,sizeof(col));
    for(int i=1;i<=n;i++)
    {
        update(1,1,n,w[i],w[i],val[i]);
    }
    while(m--)
    {
        scanf("%s",str);
        if(str[0]=='Q')
        {
            scanf("%d%d",&x,&y);
            getans(x,y,0,1);
        }
        else
        {
            scanf("%d%d%d",&x,&y,&z);
            getans(x,y,z,2);
        }
    }
    return 0;
}
/*
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
 
 
3
1
2
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值