Colorful tree
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的更多相关文章
- 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 ...
- hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。
/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...
- AtCoder Beginner Contest 133 F Colorful Tree
Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...
- HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1
/* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...
- [HDU6793] Tokitsukaze and Colorful Tree
题目 又是一个条历新年,窗前的灼之花又盛开了. 时隔多年,现在只有这一棵树上盛开着残存的 \(n\) 朵灼之花了. 尽管如此,这些灼之 花仍散发出不同色彩的微弱的光芒. 灼之花的生命极为短暂,但它的花 ...
- 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 ...
- HDU-6035:Colorful Tree(虚树+DP)
这里有三道长得像的题: 一:HDU6036: There is a tree with nn nodes, each of which has a type of color represented ...
- ABC133F - Colorful Tree
ABC133FColorful Tree 题意 给定一颗边有颜色和权值的树,多次询问,每次询问,首先更改颜色为x的边的权值为y,然后输出u到v的距离. 数据都是1e5量级的. 思路 我自己一开始用树链 ...
- HDU6035 Colorful Tree
题目链接:https://vjudge.net/problem/HDU-6035 题目大意: 多样例输入. 对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树, ...
随机推荐
- 设计模式学习——策略模式(Strategy Pattern)
0. 前言 最近在重构公司的一个项目的时候,在抽取DES加密重复部分代码的时候,突然间想起了策略模式,感觉策略模式好像可以应用上,于是重新学习了下策略模式.注:在DES加密中,有DES和TDES算法, ...
- VS代码段扩展Snippet Designer is a Visual Studio plug in which allows you to create and search for snippets inside the IDE
Snippet Designer is a Visual Studio plug in which allows you to create and search for snippets insid ...
- Java 线程Thread.Sleep详解
我们可能经常会用到 Thread.Sleep 函数来使线程挂起一段时间.那么你有没有正确的理解这个函数的用法呢? 思考下面这两个问题: 1.假设现在是 2008-4-7 12:00:00.000,如果 ...
- 软件安装失败,导致ubuntu软件中心软件消失
感谢百度上各位IT界朋友的帮助,由于某个软件安装失败,导致ubuntu软件中心软件消失的解决办法: 找百度,有人说, 使用命令:sudo apt-get install software-center ...
- background的css 排列顺序写法?
可以按顺序设置如下属性(可点击进入相应的css手册查看使用): background-color 背景颜色 background-image 背景图片 background-repeat 背景重复 b ...
- PHP中获取内网用户MAC地址(WINDOWS/linux)的实现代码
做一个内网根据MAC地址自动登录的应用,在WINDOW 2003可以正常使用,函数如下 复制代码 代码如下: function ce_getmac() { if(PHP_OS == 'WINNT' ...
- Java五道输出易错题解析(避免小错误)
收集了几个易错的或好玩的Java输出题,分享给大家,以后在编程学习中稍微注意下就OK了. 1. 看不见的空格? 下面的输出会正常吗? package basic; public class Integ ...
- [原] Intellij IDEA开发Android,祝还在使用eclipse的早日脱离苦海
注: 现在推荐使用Android Studio,以后google在Android Studio上个性差异化的东西越来越多, 所以越早使用Android Studio越好,看看更新文档,使我们开发更方便 ...
- POJ 1925 Spiderman
Spiderman Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5858 Accepted: 1143 Description ...
- maven 项目配置
创建java web的maven项目方法有两种,一是先创建maven项目,再选择jdk 和 dynamic web 运行环境 ,二是创建java项目,然后转化为maven项目 1.将普通java项目转 ...