题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5029
题意:给出一棵树,和一种操作。 操作a,b,k相当于将树上a,b结点间的路径上的节点都加上一个k值,最后输出每个结点被加最多次的那个数。
思路:先用树链剖分将问题转化到线性结构上,然后来考虑如何在线性来解决这个问题。 相当于区间染色,最后问每个点被染次数最多的那个颜色。
做法:对于每个操作a,b,k,我们将a节点上标记一个k,b+1节点上标记一个-k,多个不标记我们可以用vector来存储,先将所有的操作都打到这个线性的结构上,再用线段树来维护.
区间a~b上维护的是从颜色a到颜色b出现最多的颜色的标号,这样的话我们可以从左向右来扫描打好标记的线性结构,扫到每个节点都将他所存储的标号更新到线段树上,如果标记
是正值就将对应的颜色的次数+1,否则-1,将所有的标记都传完后,取根节点的值(维护的是整个区间)就能够知道当前被染次数最多的值。 感觉方法十分的巧妙。
code:
#include
#include
#include
#include
#include
#include
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn=105000;
const int maxe=400010;
struct edge
{
int to,next;
} P[maxe];
int head[maxn],si;
int fa[maxn],deep[maxn],son[maxn],num[maxn];
int top[maxn],p[maxn],fp[maxn],pos;
void init()
{
si=0;
memset(head,-1,sizeof(head));
pos=1;
memset(son,-1,sizeof(son));
}
void add_edge(int s,int t)
{
P[si].to=t;
P[si].next=head[s];
head[s]=si++;
}
void dfs1(int u,int pre,int d)
{
deep[u]=d;
fa[u]=pre;
num[u]=1;
for(int i=head[u];i!=-1;i=P[i].next){
int v=P[i].to;
if(v!=pre){
dfs1(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
}
}
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=pos++;
fp[p[u]]=u;
if(son[u]==-1) return ;
getpos(son[u],sp);
for(int i=head[u];i!=-1;i=P[i].next){
int v=P[i].to;
if(v!=son[u]&&v!=fa[u]) getpos(v,v);
}
}
vector w[maxn];
void add(int u,int v,int tt)
{
int f1=top[u],f2=top[v];
while(f1!=f2){
if(deep[f1]deep[v]) swap(u,v);
w[p[u]].push_back(tt);
w[p[v]+1].push_back(-tt);
}
//线段树部分
int n,cc[maxn];
struct ppp
{
int l,r,dat;
} ss[4*maxn+10];
void Build(int k,int ll,int rr)
{
ss[k].l=ll;
ss[k].r=rr;
if(ll==rr){
ss[k].dat=ll;
return ;
}
else ss[k].dat=0;
Build((k<<1)+1,ll,(ll+rr)/2);
Build((k<<1)+2,(ll+rr)/2+1,rr);
}
void init_tree(int n_)
{
n=1;
while(n0){
k=(k-1)/2;
if(cc[ss[2*k+1].dat]>=cc[ss[2*k+2].dat])
ss[k].dat=ss[2*k+1].dat;
else
ss[k].dat=ss[2*k+2].dat;
}
}
int ans[maxn];
int main()
{
int nn,mm,col;
int s,t,tt;
while(scanf("%d%d",&nn,&mm),nn!=0||mm!=0){
init();
col=0;
memset(ans,0,sizeof(ans));
memset(cc,0,sizeof(cc));
for(int i=1;i0) update(w[i][j],1);
else update(-w[i][j],-1);
}
ans[fp[i]]=ss[0].dat;
}
for(int i=1;i<=nn;i++) printf("%d\n",ans[i]);
}
return 0;
}