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

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<cctype>
using namespace std; const int Maxn=,Maxm=Maxn; int n,m; const int D=;
char in[D],out[D/],*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==) pc('');
if(x<) pc('-'),x=-x;
static int stk[],top;
top=;
for(;x;x/=) stk[++top] = x%;
for(int i=top;i;--i) pc(stk[i]+'');
} template <typename Q>
inline void gt(Q& x){
static char c,f;
for(c=gc(),f=;!isdigit(c);c=gc()) if(c=='-') f=;
for(x=;isdigit(c);c=gc()) x=x*+c-'';
if(f) x=-x;
} struct Data {
int l,r,num;
Data (int l=-,int r=-,int num=):l(l),r(r),num(num) {}
Data operator + (const Data& rhs)const {
if(rhs.l==- && l==- ) exit(-);
if(rhs.l==-) return *this;
if(l==-) 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*];
int tag[Maxn*];
int lft,rgt,w; SegmentTree() {
memset(tag,-,sizeof tag);
} void build(int o,int l,int r){
if(l==r) {
da[o] = Data(tbld[l],tbld[l],);
return;
}
int mid=(l+r)>>;
build(o<<,l,mid);
build(o<<|,mid+,r);
da[o] = da[o<<] + da[o<<|];
} void add(int o,int col) {
da[o]=Data(col,col,);
tag[o]=col;
} void down(int o) {
if(tag[o]==-) return;
add(o<<,tag[o]);
add(o<<|,tag[o]);
tag[o]=-;
} void pp(int l,int r=,int w=) {
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)>>;
if(lft<=mid) change(o<<,l,mid);
if(mid<rgt) change(o<<|,mid+,r);
da[o]=da[o<<]+da[o<<|];
} Data query(int o,int l,int r) {
if(lft<=l && r<=rgt) {
return da[o];
}
down(o);
int mid=(l+r)>>;
if(rgt<=mid) return query(o<<,l,mid);
if(mid<lft) return query(o<<|,mid+,r);
return query(o<<,l,mid)+query(o<<|,mid+,r);
} Data query(int l,int r){
pp(l,r);
return query(,,n);
} void change2(int l,int r,int w){
pp(l,r,w);
change(,,n);
}
} seg; int fir[Maxn],next[Maxm*],en[Maxm*];
int tot=;
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] = ;
son[u] = ;
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]+;
dfs(v);
sz[u] += sz[v];
if(sz[v]>sz[son[u]]) son[u] = v;
}
} int top[Maxn],pos[Maxn],color[Maxn],clk=; 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,,D,stdin); gt(n),gt(m); for(int i=;i<=n;i++) gt(color[i]); for(int u,v,i=;i<n;i++){
gt(u),gt(v);
Add(u,v);
Add(v,u);
} dfs();
build(,);
seg.build(,,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),;
}

嗯,其实lct还是挺好写的,就是有点慢TAT

 #include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
using namespace std; const int Maxn = ; int ch[Maxn][],p[Maxn],sz[Maxn],flip[Maxn],tag[Maxn];
int col[Maxn];
int n,m; const int D=;
char in[D],out[*],*I=in,*O=out;
#define gc (*I++)
#define pc(x) ((*O++)=x)
template <typename Q>
void gt(Q&x) {
static char c,f;
for(c=gc,f=;!isdigit(c);c=gc)if(c=='-') f=;
for(x=;isdigit(c);c=gc) x=x*+c-'';
f && (x=-x);
} struct Data {
int l,r,num;
Data(int l=-,int r=-,int num=):l(l),r(r),num(num) {}
Data operator + (const Data& rhs) const {
if(!num) return rhs;
if(!rhs.num) return *this;
return Data (l,rhs.r,num+rhs.num-(r==rhs.l));
}
void flip() {
swap(l,r);
}
}da[Maxn]; template <typename Q>
void pt(Q x){
static char stk[];
static int top;
top=;
if(x==) pc('');
for(;x;x/=) stk[++top] = x%+'';
for(;top;top--) pc(stk[top]);
} int fir[Maxn],next[Maxn*],en[Maxn*];
void Add(int from,int to) {
static int tot=;
en[++tot]=to;
next[tot]=fir[from];
fir[from]=tot;
} void add_tag(int x,int Col) {
if(x==) return;
col[x] = tag[x] = Col;
da[x] = Data(Col,Col,);
} void down(int x) {
if(flip[x]) {
swap(ch[x][],ch[x][]);
flip[ch[x][]]^=; da[ch[x][]].flip();
flip[ch[x][]]^=; da[ch[x][]].flip();
flip[x]=;
}
if(tag[x]!=-) {
add_tag(ch[x][],tag[x]);
add_tag(ch[x][],tag[x]);
tag[x]=-;
}
} bool isroot(int x){
return ch[p[x]][]!=x && ch[p[x]][]!=x;
} void update(int x) {
if(x==) return;
sz[x]=sz[ch[x][]]+sz[ch[x][]]+;
da[x]=da[ch[x][]]+Data(col[x],col[x],)+da[ch[x][]];
} void rotate(int x) {
int y=p[x],z=p[y];
int l=ch[y][]==x,r=l^;
if(!isroot(y)) ch[z][ch[z][]==y]=x;
p[ch[x][r]]=y;
p[y]=x;
p[x]=z; ch[y][l]=ch[x][r];
ch[x][r]=y; update(y);
update(x);
} void splay(int x){
static int stk[Maxn],top;
stk[top=]=x;
for(int t=x;!isroot(t);t=p[t]) stk[++top] = p[t];
for(;top;top--) down(stk[top]);
for(;!isroot(x);){
int y=p[x],z=p[y];
if(!isroot(y)){
if( (ch[y][]==x)^(ch[z][]==y) )
rotate(x);else rotate(y);
}
rotate(x);
}
} void access(int x){
for(int t=;x;x=p[t=x]){
splay(x);
ch[x][]=t;
update(x);
}
} int getroot(int x){
for(access(x),splay(x);ch[x][];x=ch[x][]);
return x;
} void cut(int x){
access(x);
splay(x);
p[ch[x][]]=;
ch[x][]=;
update(x);
} void combine(int x,int y) {
cut(x);
p[x]=y;
update(y);
} void newroot(int x){
access(x);
splay(x);
flip[x]^=;
da[x].flip();
} void dfs(int x) {
for(int k=fir[x];k;k=next[k]) {
int v=en[k];
if(v==p[x]) continue;
p[v]=x;
dfs(v);
}
} void init(){
gt(n);gt(m);
memset(tag,-,sizeof(*tag)*(n+));
for(int i=;i<=n;i++) {
gt(col[i]);
sz[i]=;
da[i] = Data( col[i],col[i],);
}
for(int u,v,i=;i<n;i++) {
gt(u),gt(v);
Add(u,v);
Add(v,u);
}
dfs();
} void work() {
char cmd;
int a,b,c;
for(int i=;i<=m;i++) {
for(cmd=gc;cmd!='C' && cmd!='Q';cmd=gc);
gt(a);gt(b);
newroot(a);
access(b);
splay(b);
if(cmd=='C') {
gt(c);
add_tag(b,c);
}else {
pt(da[b].num);
pc('\n');
}
}
}
int main() {
#ifdef DEBUG
freopen("paint.in","r",stdin);
freopen("paint.out","w",stdout);
#endif
fread(in,,D,stdin); init();
work(); return printf(out),;
}

bzoj2243 sdoi2011 染色 paint的更多相关文章

  1. BZOJ2243 SDOI2011 染色 【树链剖分】

    BZOJ2243 SDOI2011 染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色 ...

  2. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

  3. [bzoj2243][SDOI2011]染色

    Description 给定一棵有$n$个节点的无根树和$m$个操作,操作有$2$类: 1.将节点$a$到节点$b$路径上所有点都染成颜色$c$; 2.询问节点$a$到节点$b$路径上的颜色段数量(连 ...

  4. BZOJ2243[SDOI2011]染色——树链剖分+线段树

    题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221 ...

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

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

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

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  7. BZOJ2243: [SDOI2011]染色(树链剖分/LCT)

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...

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

    此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...

  9. BZOJ2243——[SDOI2011]染色

    1.题目大意:给个树,然后树上每个点都有颜色,然后会有路径的修改,有个询问,询问一条路径上的颜色分成了几段 2.分析:首先这个修改是树剖可以做的,对吧,但是这个分成了几段怎么搞呢,我们的树剖的不是要建 ...

随机推荐

  1. PHP替换中文字符

    mb_regex_encoding('utf-8');$htmlNavSubmenu2 = str_replace('<li id="w-menu-food-334"> ...

  2. javaScript 的option触发事件

    先说jquery的option触发事件,很方便 $("option:selected")//这样就能直接触发选择的option了 在JavaScript中就显得比较麻烦,其实< ...

  3. [C#]获取最近在Windows上所使用的文件

    class RecentlyFileHelper { public static string GetShortcutTargetFile(string shortcutFilename) { var ...

  4. this详解:JAVASCRIPT中的this到底是谁?

    语法 this 全局对象 在全局执行上下文(函数之外),this引用的是全局对象. console.log(this.document === document); // true // In web ...

  5. Bootstrap_网格系统

    首先添加CSS样式: [class *= col-]{ background-color: #eee; border: 1px solid #ccc; } [class *= col-] [class ...

  6. 【技术宅11】php入门运算

    //1.空bool $a=''; $b=NULL; $c=false; $d=0; $e='0'; $f=array(); $g=array(array()); $h='NULL'; var_dump ...

  7. php 获取域名的whois 信息

    首先先了解几个文件操作函数: fwrite() 函数写入文件(可安全用于二进制文件). fwrite() 把 string 的内容写入文件指针 file 处. 如果指定了 length,当写入了 le ...

  8. unix-环境高级编程-读书笔记与习题解答-第三篇

    第一章 第五节 进程与控制 该小节比较粗略的阐述了unix操作系统中用于进程控制的三个函数,分别为 : fork , exec, waitpid, 其中 exec 有五种变体, 这些变体实现的功能全部 ...

  9. Leetcode: Reverse Integer 正确的思路下-要考虑代码简化

    题目: Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 Have ...

  10. Solr4.8.0源码分析(25)之SolrCloud的Split流程

    Solr4.8.0源码分析(25)之SolrCloud的Split流程(一) 题记:昨天有位网友问我SolrCloud的split的机制是如何的,这个还真不知道,所以今天抽空去看了Split的原理,大 ...