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)\) 个结点的一棵树, ...
随机推荐
- POJ 2389 Bull Math(水~Java -大数相乘)
题目链接:http://poj.org/problem?id=2389 题目大意: 大数相乘. 解题思路: java BigInteger类解决 o.0 AC Code: import java.ma ...
- MathML + MathJax在网页中插入公式
http://www.mathjax.org/download/ http://www.w3.org/Math/Software/mathml_software_cat_editors.html ht ...
- 【转】SPDY协议
SPDY协议 - v3 原文:SPDY Protocol - Draft 3 翻译:邱鹏滔(QQ: 95350530,主页:www.fireflysource.com) 1 概述 HTTP协议的瓶颈在 ...
- MVC下的客户端模板技术
1.引言 在Web编程中,我们有时经常需要使用Ajax来访问服务端的接口,然后使用这些返回的数据(一般格式都是JSON)来展示客户端的相关信息.例如:在一个商品列表,我们点击某一样的商品,查看该商品的 ...
- Mongodb 资源
一.资源 1.C# 驱动下载地址 https://github.com/mongodb/mongo-csharp-driver/releases 2. Mongodb 管理工具 mongochef 下 ...
- Java Lambda表达式入门
Java Lambda表达式入门 http://blog.csdn.net/renfufei/article/details/24600507 Java 8十个lambda表达式案例 http://w ...
- 几种常用的JS类定义方法(转)
// 方法1 对象直接量 var obj1 = { v1 : "", get_v1 : function() { return this.v1; }, set_v1 : funct ...
- Unity相关路径
Application.dataPath 只读 在项目根目录下读取文件,但移动端没有访问权限.一般适用于PC端调试用. Application.streamingAssetsPath 在Assets目 ...
- ASO优化总结(基于网络分享的知识总结归纳)
如何优化应用标题? 注意关键字的长度,尽量保证每一个关键字小于10个字符.保持快速更新,因为每次更新,你都将有机会删除表现不佳的关键字以 及增添新的关键字.在ASO中使用关键字的正确做法 标题,并非越 ...
- 必须知道的.net(字段、属性和方法)
1.字段 通常定义为private(封装原则) 2.属性(property) 通常定义为public,表示类的对外成员.具有可读可写属性,通过get和set访问器实现 3.索引器(indexer) C ...