cnbb 我被数组清零卡了一天..

子树改色询问子树颜色数..

先考虑颜色为x的节点对祖先答案的贡献,那么我们考虑把所有这些节点都搞出来,按dfs序排序,然后考虑每个节点a掌管的祖先是它和按dfs序的下一个同色节点b的LCA以下的节点,然后每个有颜色x儿子的树都被覆盖了,而且最多覆盖一次.

在删除节点的时候考虑将所有它的儿子删去变成一棵只有根节点的树.

统计答案的时候要考虑父亲的贡献..即若这个节点的颜色在它子树中出现了答案就不+1,否则答案+1.

cnbb的多组数据, fuck you.

数据复杂度\(O((n+q)\log{n})\)

至于为什么是这样注意到加入节点的次数是\(O(n+q)\)的,加入或删去一个节点的复杂度是\(O(\log{n})\)的.

树上链加单点查询只需要考虑儿子对它所有祖先的贡献,然后改区间询问单点修改就可以了,BIT维护.

#include <set>
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
// Contants & usable functions
using namespace std;
const int N = 500010;
// Debug functions(mostly macros)
int out(int p){ return p; }
typedef int(*FII)(int);
#ifdef MacroDebug
#define debug(...) { fprintf(stderr, ##__VA_ARGS__); fflush(stdout); }
inline void printset(set<int> p, FII Fn=out){
debug("Set :");
for(set<int>::iterator k=p.begin();k!=p.end();++k) debug(" %d",Fn(*k));
debug("\n");
}
#else
#define debug(...)
inline void printset(set<int> p, FII Fn=out){}
#endif
// Tree(LCA, Left, Right, DfsSeq, Depth, Size)
struct ed{
int t;
ed*n;
}*h[N],Al[N<<1],*p=Al;
inline void ade(int f,int t){ *p=(ed){t,h[f]}; h[f]=p++; }
int DfsSeq[N<<1] , DfsMark ;
int Left [N] , Right[N];
int Father[N] , Size [N];
int maxson[N] , Depth[N];
int dfs(int t,int f=0){
Father[t]=f, ++DfsMark, Size[t]=1, Depth[t]=Depth[f]+1;
Left[DfsSeq[DfsMark]=t]=DfsMark;
for(ed*i=h[t];i;i=i->n)if(i->t!=f){
Size[t]+=dfs(i->t,t);
if(Size[i->t]>Size[maxson[t]]) maxson[t]=i->t;
} Right[t]=DfsMark;
return Size[t];
}
inline void clearTree(){ for(int i=0;i<=DfsMark;++i) h[i]=NULL,Depth[i]=maxson[i]=Size[i]=0; p=Al; } #ifdef MacroDebug
int OutUnSeq(int t){ return DfsSeq[t]; }
#else
const FII OutUnSeq=out;
#endif int top[N];
int dfs2(int t,int Top){
top[t]=Top;
if(maxson[t]) dfs2(maxson[t],Top);
for(ed*i=h[t];i;i=i->n)if(i->t!=Father[t]&&i->t!=maxson[t]) dfs2(i->t,i->t);
}
inline int LCA(int u,int v){
int fu=top[u], fv=top[v];
while(fu!=fv){
if(Depth[fu]<Depth[fv]) swap(fu,fv),swap(u,v);
u=Father[fu];
fu=top[u];
} return Depth[u]<Depth[v]?u:v;
}
// Path add, point query
#define lb(x) (x&-x)
template<int T=N<<1> struct BIT{
int bitarr[T],siz;
inline void clear(){ for(int i=0;i<=siz;++i) bitarr[i]=0; siz=0; }
inline void init(int n){ clear(), siz=n; }
inline void add(int t,int w){ for(;t<=siz;t+=lb(t)) bitarr[t]+=w; }
inline int sum(int t){ int ans=0; for(;t;t-=lb(t)) ans+=bitarr[t]; return ans; }
inline int sum(int l,int r){ return sum(r)-sum(l-1); }
};
BIT<> TPU;
inline void Add(int f,int t,int g=1){
debug("1: %d %d %d\n",f,t,g);
TPU.add(Left[f],g);
if(t) TPU.add(Left[t],-g);
}
inline int Qry(int f){ return TPU.sum(Left[f],Right[f]); }
// The colors on the tree
namespace colorSeg{
int col[N<<2];
void build(int i,int l,int r){
col[i]=-1;
if(l==r){
col[i]=0;
return;
} int mid=(l+r)>>1;
build(i<<1,l,mid), build(i<<1|1,mid+1,r);
}
inline void pd(int t){ if(~col[t]) col[t<<1]=col[t<<1|1]=col[t], col[t]=-1; }
void upd(int i,int l,int r,int ql,int qr,int cl){
if(ql<=l && r<=qr) col[i]=cl;
else{ int mid=(l+r)>>1; pd(i);
if(ql<=mid) upd(i<<1,l,mid,ql,qr,cl);
if(qr> mid) upd(i<<1|1,mid+1,r,ql,qr,cl);
}
}
int GetColor(int i,int l,int r,int t){ int mid=(l+r)>>1;
if(l==r) return col[i];
else return pd(i),(t<=mid)?GetColor(i<<1,l,mid,t):GetColor(i<<1|1,mid+1,r,t);
} inline void set(int f,int val){ upd(1,1,DfsMark,Left[f],Right[f],val); }
inline int get(int f){ return GetColor(1,1,DfsMark,Left[f]); }
};
// Stores All Colors & Deletable Tree
typedef set<int> si;
typedef si::iterator sit;
si colors[N];
int Pcolor[N];
int PathUpto[N];
inline void Reinit(int nk){ for(int i=1;i<=nk;++i) colors[i].clear(), PathUpto[i]=-1; }
inline void ReColor(int q,int RecolorQ=-1){
debug("Recolor %d -- %d\n",q,RecolorQ);
if(~PathUpto[q]){
debug("FStart\n");
Add(q,PathUpto[q],-1), PathUpto[q]=-1;
colors[Pcolor[q]].erase(Left[q]);
debug("Color %d ",Pcolor[q]);
printset(colors[Pcolor[q]],OutUnSeq);
debug("FEnd\n");
} if(~RecolorQ) Pcolor[q]=RecolorQ;
if(Pcolor[q]){
int colorx=Pcolor[q];
debug("Color %d ",colorx);
printset(colors[colorx],OutUnSeq);
sit v=colors[colorx].lower_bound(Left[q]);
if(v!=colors[colorx].end()){
int ar=DfsSeq[*v];
PathUpto[q]=LCA(q,ar);
}else PathUpto[q]=0;
debug("Update PathUpto %d\n",PathUpto[q]);
Add(q,PathUpto[q]);
colors[colorx].insert(Left[q]);
}
}
inline void deletePoint(int t){
if(int qc=Pcolor[t]){
ReColor(t,0);
sit k=colors[qc].lower_bound(Left[t]);
if(k!=colors[qc].begin()) ReColor(DfsSeq[*(--k)]);
}
}
inline void insertPoint(int t,int color){
deletePoint(t);
if(color){
ReColor(t,color);
debug("Color %d Find %d ",color,t);
printset(colors[color],OutUnSeq);
sit v=colors[color].find(Left[t]);
if(v!=colors[color].begin()) ReColor(DfsSeq[*(--v)]);
}
}
namespace treeSeg{
int Has[N<<2];
void build(int i,int l,int r){
Has[i]=0; int mid=(l+r)>>1;
if(l==r) return;
build(i<<1,l,mid), build(i<<1|1,mid+1,r);
}
int sum(int i,int l,int r,int ql,int qr,int ans=0){ int mid=(l+r)>>1;
if(ql<=l && r<=qr) return Has[i];
else{
if(ql<=mid) ans+=sum(i<<1,l,mid,ql,qr);
else ans+=sum(i<<1|1,mid+1,r,ql,qr);
return ans;
}
}
int clr(int i,int l,int r,int ql,int qr){ int mid=(l+r)>>1;
if(l==r) deletePoint(DfsSeq[l]),Has[i]=0;
else{
if(ql<=mid && Has[i<<1]) clr(i<<1,l,mid,ql,qr);
if(qr> mid && Has[i<<1|1]) clr(i<<1|1,mid+1,r,ql,qr);
Has[i]=Has[i<<1]+Has[i<<1|1];
}
}
void set(int i,int l,int r,int t){
if(l==r){
Has[i]=1;
return;
}
int mid=(l+r)>>1;
if(t<=mid) set(i<<1,l,mid,t);
else set(i<<1|1,mid+1,r,t);
Has[i]=Has[i<<1]+Has[i<<1|1];
}
inline void Color(int f){ set(1,1,DfsMark,Left[f]); }
inline void Delete(int f){ if(Left[f]==Right[f]) return; clr(1,1,DfsMark,Left[f]+1,Right[f]); }
};
inline void Color(int f,int val){
insertPoint(f,val);
treeSeg::Delete(f);
treeSeg::Color (f);
colorSeg::set(f,val);
}
inline int Query(int f){
int ccol=colorSeg::get(f);
int target=0x7fffffff;
sit v=colors[ccol].lower_bound(Left[f]);
if(v!=colors[ccol].end()) target=*v;
return (Qry(f)+1)-(target<=Right[f]?1:0);
}
inline void Work(int t){
static int vc[N];
printf("Case #%d:\n",t);
clearTree();
int n; scanf("%d",&n);
for(int i=1,a,b;i<n;++i){
scanf("%d%d",&a,&b);
ade(a,b); ade(b,a);
}
DfsMark=0;
dfs(1), dfs2(1,1);
TPU.init(DfsMark);
colorSeg::build(1,1,DfsMark);
treeSeg ::build(1,1,DfsMark);
Reinit(n);
for(int i=1;i<=n;++i)
colors[i].clear();
for(int i=1;i<=n;++i)
scanf("%d",vc+i), Pcolor[i]=0;
for(int i=1;i<=n;++i)
Color(DfsSeq[i],vc[DfsSeq[i]]);
int q; scanf("%d",&q);
for(int i=1;i<=q;++i){
int a,u,c;
scanf("%d%d",&a,&u);
if(a){
int q=Query(u);
printf("%d\n",q);
debug("%d\n",q);
}
else scanf("%d",&c),Color(u,c);
}
}
int main(){
int t; scanf("%d",&t);
for(int i=1;i<=t;++i) Work(i);
return 0;
}

Colorful tree的更多相关文章

  1. 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】

    Colorful Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  2. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  3. AtCoder Beginner Contest 133 F Colorful Tree

    Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...

  4. HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1

    /* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...

  5. [HDU6793] Tokitsukaze and Colorful Tree

    题目 又是一个条历新年,窗前的灼之花又盛开了. 时隔多年,现在只有这一棵树上盛开着残存的 \(n\) 朵灼之花了. 尽管如此,这些灼之 花仍散发出不同色彩的微弱的光芒. 灼之花的生命极为短暂,但它的花 ...

  6. 2017ACM暑期多校联合训练 - Team 1 1003 HDU 6035 Colorful Tree (dfs)

    题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...

  7. HDU-6035:Colorful Tree(虚树+DP)

    这里有三道长得像的题: 一:HDU6036: There is a tree with nn nodes, each of which has a type of color represented ...

  8. ABC133F - Colorful Tree

    ABC133FColorful Tree 题意 给定一颗边有颜色和权值的树,多次询问,每次询问,首先更改颜色为x的边的权值为y,然后输出u到v的距离. 数据都是1e5量级的. 思路 我自己一开始用树链 ...

  9. HDU6035 Colorful Tree

    题目链接:https://vjudge.net/problem/HDU-6035 题目大意: 多样例输入. 对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树, ...

随机推荐

  1. Unity Sprite Atlas Compression

    http://forum.unity3d.com/threads/2d-sprite-packer-and-pvrtc.218633/ http://docs.unity3d.com/Manual/S ...

  2. Linux笔记-常用的命令(15-3-30)

    vim命令参考: http://www.cnblogs.com/softwaretesting/archive/2011/07/12/2104435.html [1]解压文件格式的区别: *.tar  ...

  3. [c#]获取exchange中的图片

    摘要 在exchange 2007或者2010中获取的邮件内容为html标签格式,也就是一个页面.如果里面含有img标签,你会发现img标签的src属性为cid:xxxxxxxxxxxx的一串字符串, ...

  4. jq实现鼠标移动到 图片上放大,移开图片缩小效果(打算封装成插件)

    先看代码 <script> $(function() { $('div').mouseover(function() { $('img').animate({ opacity: '0.9' ...

  5. python 运行时报错误SyntaxError: Non-ASCII character '\xe5' in file 1.py on line 2

    File "1.py", line 2SyntaxError: Non-ASCII character '\xe5' in file 1.py on line 2, but no ...

  6. ThinkPHP3.2对接开发支付宝即时到帐接口

    ThinkPHP3.2对接开发支付宝即时到帐接口 在做一些商城.自动发卡网站.会员积分充值.金币充值等等这类网站都时候,我们极大可能需要使用到第三方都支付接口.不管是财付通.支付宝.银联.贝宝.易宝这 ...

  7. 【AngularJS】—— 11 指令的交互

    前面基本了解了指令的相关内容: 1 如何自定义指令 2 指令的复用 本篇看一下指令之间如何交互.学习内容来自<慕课网 指令3> 背景介绍 这例子是视频中的例子,有一个动感超人,有三种能力, ...

  8. Excel 使用宏批量修改单元格内指定文字为红字

    -> step 1:新建宏,进入编辑,使用如下代码: Sub Ss()Dim c As RangeFor Each c In ActiveSheet.UsedRange i = 1 While ...

  9. [Linux] Chang DNS Setting on Linux

    主机的虚拟机使用 NAT 模式时, NAT的DNS不好用.于是需要将虚拟机的DNS改成和主机的一样,这样虚拟机也可以请求互联网资源. Linux的DNS 服务器定义在 /etc/resolv.conf

  10. POJ 1265 Area

    有一种定理,叫毕克定理....                             Area Time Limit: 1000MS   Memory Limit: 10000K Total Sub ...