bzoj2243 sdoi2011 染色 paint

明明是裸树剖 竟然调了这么久好蛋疼 大概是自己比较水的原因吧 顺便+fastio来gangbang

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<cctype>
using namespace std;

const int Maxn=100010,Maxm=Maxn;

int n,m;

const int D=1000000;
char in[D],out[D/10],*I=in,*O=out;

inline char gc(){
    return *(I++);
}

inline void pc(const char& c){
    *(O++)=c;
}

template <typename Q>
inline void pt(Q x){
    if(x==0) pc(‘0‘);
    if(x<0) pc(‘-‘),x=-x;
    static int stk[20],top;
    top=0;
    for(;x;x/=10) stk[++top] = x%10;
    for(int i=top;i;--i) pc(stk[i]+‘0‘);
}

template <typename Q>
inline void gt(Q& x){
    static char c,f;
    for(c=gc(),f=0;!isdigit(c);c=gc()) if(c==‘-‘) f=1;
    for(x=0;isdigit(c);c=gc()) x=x*10+c-‘0‘;
    if(f) x=-x;
}

struct Data {
    int l,r,num;
    Data (int l=-1,int r=-1,int num=0):l(l),r(r),num(num) {}
    Data operator + (const Data& rhs)const {
        if(rhs.l==-1 && l==-1 ) exit(-1);
        if(rhs.l==-1) return *this;
        if(l==-1) return rhs;
        return Data(l,rhs.r,num+rhs.num-(r==rhs.l));
        Data ret(l,rhs.r,num+rhs.num);
        if(r==rhs.l) ret.num--;
        return ret;
    }
    Data operator ~()const {
        return Data(r,l,num);
    }
};

int tbld[Maxn];

struct SegmentTree {
    Data da[Maxn*4];
    int tag[Maxn*4];
    int lft,rgt,w;

    SegmentTree() {
        memset(tag,-1,sizeof tag);
    }

    void build(int o,int l,int r){
        if(l==r) {
            da[o] = Data(tbld[l],tbld[l],1);
            return;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
        da[o] = da[o<<1] + da[o<<1|1];
    }

    void add(int o,int col) {
        da[o]=Data(col,col,1);
        tag[o]=col;
    }

    void down(int o) {
        if(tag[o]==-1) return;
        add(o<<1,tag[o]);
        add(o<<1|1,tag[o]);
        tag[o]=-1;
    }

    void pp(int l,int r=0,int w=0) {
        lft=l,rgt=r;
        this->w=w;
    }

    void change(int o,int l,int r) {
        if(lft<=l && r<=rgt) {
            add(o,w);
            return;
        }
        down(o);
        int mid=(l+r)>>1;
        if(lft<=mid) change(o<<1,l,mid);
        if(mid<rgt) change(o<<1|1,mid+1,r);
        da[o]=da[o<<1]+da[o<<1|1];
    }

    Data query(int o,int l,int r) {
        if(lft<=l && r<=rgt) {
            return da[o];
        }
        down(o);
        int mid=(l+r)>>1;
        if(rgt<=mid) return query(o<<1,l,mid);
        if(mid<lft) return query(o<<1|1,mid+1,r);
        return query(o<<1,l,mid)+query(o<<1|1,mid+1,r);
    }

    Data query(int l,int r){
        pp(l,r);
        return query(1,1,n);
    }

    void change2(int l,int r,int w){
        pp(l,r,w);
        change(1,1,n);
    }
} seg;

int fir[Maxn],next[Maxm*2],en[Maxm*2];
int tot=0;
void Add(int from,int to) {
    en[++tot] = to;
    next[tot] = fir[from];
    fir[from] = tot;
}

int sz[Maxn],son[Maxn],fa[Maxn],dep[Maxn];

void dfs(int u) {
    sz[u] = 1;
    son[u] = 0;
    for(int k=fir[u]; k; k=next[k]) {
        const int&v=en[k];
        if(v == fa[u]) continue;
        fa[v] = u;
        dep[v] = dep[u]+1;
        dfs(v);
        sz[u] += sz[v];
        if(sz[v]>sz[son[u]]) son[u] = v;
    }
}

int top[Maxn],pos[Maxn],color[Maxn],clk=0;

void build(int u,int pre) {
    top[u] = pre;
    pos[u] = ++clk;
    tbld[clk] = color[u];
    if(son[u]) build(son[u],pre);
    for(int k=fir[u]; k; k=next[k]) {
        const int&v = en[k];
        if(v==fa[u] || v==son[u]) continue;
        build(v,v);
    }
}

void change(int a,int b,int c){
    int ta=top[a],tb=top[b];
    for(;ta!=tb;a=fa[ta],ta=top[a]){
        if(dep[ta] < dep[tb] ) swap(a,b), swap(ta,tb);
        seg.change2(pos[ta],pos[a],c);
    }
    if(dep[a]>dep[b]) swap(a,b);
    seg.change2(pos[a],pos[b],c);
}

Data query(int a,int b) {
    int ta=top[a],tb=top[b];

    Data res1,res2;

    for(;ta!=tb;){
        if(dep[ta]>dep[tb]){
            res1 = seg.query(pos[ta],pos[a]) + res1;//注意这里以及下面加的顺序,写的时候没想好,调了好久
            a=fa[ta],ta=top[a];
        } else {
            res2 = seg.query(pos[tb],pos[b]) + res2;
            b=fa[tb],tb=top[b];
        }
    }
//    Data tmp ( seg.query(pos[b],pos[a]) );
    if(dep[a]<dep[b]) return (~res1)+seg.query(pos[a],pos[b])+res2;//还有这里要取反各种坑,各种要注意顺序
//     tmp=(~res2)+seg.query(pos[b],pos[a]);
//    tmp=tmp+res1;
    return (~res2)+seg.query(pos[b],pos[a])+res1;
}

int main() {
    freopen("paint.in","r",stdin);
    freopen("paint.out","w",stdout);

    fread(in,1,D,stdin);

    gt(n),gt(m);

    for(int i=1;i<=n;i++) gt(color[i]);

    for(int u,v,i=1;i<n;i++){
        gt(u),gt(v);
        Add(u,v);
        Add(v,u);
    }

    dfs(1);
    build(1,1);
    seg.build(1,1,n);

//    for(int i=1;i<=n;i++) printf("%d\n",son[i]);
//    return 0;

    char cmd;
    int a,b,c;

//    for(I=1;I<=m;I++)
    for(;m--;){

        /*if(I==2) {
            Data tmp=seg.query( pos[2],pos[7] );
            tmp=seg.query( pos[3],pos[4]);
            tmp=seg.query( pos[2],pos[6]);
            tmp=seg.query( pos[6],pos[7]);
            I=2;
        }*/

        for(cmd=gc();cmd!=‘Q‘&&cmd!=‘C‘;cmd=gc());
        gt(a);gt(b);
        if(cmd == ‘Q‘) pt(query(a,b).num),pc(‘\n‘);
        else gt(c), change(a,b,c);
    }

    return printf(out),0;
}
时间: 2024-08-26 21:01:55

bzoj2243 sdoi2011 染色 paint的相关文章

bzoj2243 [SDOI2011]染色 动态树

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 110000 int pre[N],ch[N][2]; int e[N],ne[N*2],v[N*2]; int nn,m; int col[N]; int lc[N],sm[N],rc[N],num[N]; int rt[N],n; int qu[N

BZOJ2243 [SDOI2011]染色

题意:树,路径染色,路径查询分了几段. 分析: 树链剖分套线段树,没写过,代码写得很乱,还犯了不少错,加了点注释,以后不能犯这种错了. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define m ((L+R)>>1) #define lc o<<1 #define rc o<<1|1 #define ls lc,L,m

[BZOJ2243][SDOI2011]染色 解题报告|树链剖分

Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写一个程序依次完成这m个操作. 与上一题差别不大,主要就是solve过程要根据左端点和右端点的颜色处理合并时候的情况 线段树的每个节点要记录颜色段数|最左边的颜色|最右边的颜色 同时往下传的时候标记要做好(之前那道题是单点修改所以不用考虑

BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

题目链接 BZOJ2243 树链剖分+线段树合并 线段树合并的一些细节需要注意一下 #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 100010; int n, m,

bzoj2243: [SDOI2011]染色 树链剖分

裸树剖. #include<bits/stdc++.h> using namespace std; #define N 100010 #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define L l,M,P #define R M+1,r,S #define Z int l=1,int r=n,int k=1 typedef int ds[N]; ds dp,num,p,size,son,t

[BZOJ2243]SDOI2011染色|树链剖分|LCT

裸题嘛.. 先考虑一条线段上如何查询颜色段数,只要对每个线段树节点多维护一个左颜色和右颜色,然后合并的时候sum[x]=sum[lc]+sum[rc]-(左儿子的右颜色==右儿子的左颜色)..实在太久没写树剖结果码+调试花了两节多晚自习,,各种傻逼错误,什么反向边忘加,标记忘记下传...还有就是更新答案的时候,关键的一点是要保证当前的两点(也就是a,b)是没有被更新到的,否则很难搞.. 表示LCT要更好写..不过在BZOJ上我的树链剖分6000+MS,LCT要13000+MS.. 树链剖分: #

【树链剖分】bzoj2243 [SDOI2011]染色

树链剖分模板题.线段树维护每个段中的颜色数.左端点颜色.右端点颜色. pushup: col[rt]=col[rt<<1]+col[rt<<1|1]-(Rcol[rt<<1]==Lcol[rt<<1|1]); 在合并各个链的答案时,要注意若两头颜色相同,ans--. [教训:树链剖分题在进行建立线段树树时,要注意下面代码中的标注部分.否则会WA] Code: 1 #include<cstdio> 2 #include<algorithm&g

bzoj2243: [SDOI2011]染色--线段树+树链剖分

此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加快了1.3s.. 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 100010; 6 struct node{

[BZOJ2243][SDOI2011]染色(树链剖分)

[传送门] 树链剖分就行了,注意线段树上颜色的合并 Code #include <cstdio> #include <algorithm> #define N 100010 #define MID int mid=(l+r)>>1,ls=id<<1,rs=id<<1|1 #define len (r-l+1) using namespace std; struct tree{ int lc,rc,sum,tag; tree(){lc=rc=tag