码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ2243: [SDOI2011]染色

时间:2015-12-07 22:21:21      阅读:322      评论:0      收藏:0      [点我收藏+]

标签:

Description

 

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”3段组成:“11”、“222”和“1”

请你写一个程序依次完成这m个操作。

 

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示xy之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

 

Output

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

 

Sample Input

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

Sample Output

3

1

2

HINT

 

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。

 
显然是裸题。。。
本以为动态树好写一些,然而,然而,一个SB错误瞪了2h+。
我的代码能力还能用喂狗来形容吗?
技术分享
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define lc ch[x][0]
#define rc ch[x][1]
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
    if(head==tail) {
        int l=fread(buffer,1,BufferSize,stdin);
        tail=(head=buffer)+l;
    }
    return *head++;
}
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==-) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-0;
    return x*f;
}
const int maxn=100010;
int ch[maxn][2],fa[maxn],pre[maxn],setv[maxn],val[maxn];
int sumv[maxn],left[maxn],right[maxn];
int s[maxn];
void maintain(int x) {
    if(!x) return;
    if(setv[x]) {
        left[x]=right[x]=setv[x];sumv[x]=1;
        return;
    }
    sumv[x]=sumv[lc]+sumv[rc]+1;
    if(val[x]==left[rc]) sumv[x]--;
    if(val[x]==right[lc]) sumv[x]--;
    left[x]=left[lc]?left[lc]:val[x];
    right[x]=right[rc]?right[rc]:val[x];
}
void set(int x,int v) {
    if(!x) return;
    setv[x]=val[x]=left[x]=right[x]=v;sumv[x]=1;
}
void pushdown(int x) {
    if(!x) return;
    if(setv[x]) {
        set(lc,setv[x]);set(rc,setv[x]);
        setv[x]=0;
    }
}
void rotate(int x) {
    int y=pre[x],z=pre[y],d=ch[y][0]==x;
    ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y;
    ch[z][ch[z][1]==y]=x;pre[x]=z;
    ch[x][d]=y;pre[y]=x;maintain(y);
}
int S[maxn],top;
void splay(int x) {
    for(int i=x;i;i=pre[i]) S[++top]=i;
    if(top!=1) fa[x]=fa[S[top]],fa[S[top]]=0;
    while(top) pushdown(S[top--]);
    while(pre[x]) rotate(x);
    maintain(x);
}
void access(int x) {
    for(int y=0;x;x=fa[x]) {
        splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x;
        ch[x][1]=y;pre[y]=x;maintain(y=x);
    }
}
void solve(int x,int y,int t,int v) {
    access(y);
    for(y=0;x;x=fa[x]) {
        splay(x);
        if(!fa[x]) {
            if(t) set(y,v),set(rc,v),val[x]=v,maintain(x);
            else {
                int ans=sumv[rc]+sumv[y]+1;
                if(val[x]==left[rc]) ans--;
                if(val[x]==left[y]) ans--;
                printf("%d\n",ans);
            }
            return;
        }
        pre[ch[x][1]]=0;fa[ch[x][1]]=x;
        ch[x][1]=y;pre[y]=x;maintain(y=x);
    }
}
int first[maxn],next[maxn<<1],to[maxn<<1],e;
void AddEdge(int u,int v) {
    to[++e]=v;next[e]=first[u];first[u]=e;
    to[++e]=u;next[e]=first[v];first[v]=e;
}
int Q[maxn],vis[maxn];
void bfs(int x) {
    int l=1,r=0;Q[++r]=x;vis[x]=1;
    while(l<=r) {
        x=Q[l++];
        ren if(!vis[to[i]]) {
            fa[to[i]]=x;
            Q[++r]=to[i];
            vis[to[i]]=1;
        }
    }
}
int main() {
    int n=read(),m=read();
    rep(i,1,n) set(i,read()+1);
    rep(i,2,n) AddEdge(read(),read());
    bfs(1);
    while(m--) {
        char c=getchar();while(!isalpha(c)) c=getchar();
        int u=read(),v=read(),x,t=0;
        if(c==C) x=read()+1,t=1;
        solve(u,v,t,x);
    }
    return 0;
}
View Code

 

BZOJ2243: [SDOI2011]染色

标签:

原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/5027376.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!