您的位置:首页 > 编程语言 > Qt开发

Cogs 1672. [SPOJ375 QTREE]难存的情缘 LCT,树链剖分,填坑计划

2016-03-14 22:03 471 查看

题目:http://cojs.tk/cogs/problem/problem.php?pid=1672

1672. [SPOJ375 QTREE]难存的情缘

★★★☆ 输入文件:
qtree.in
输出文件:
qtree.out
简单对比
时间限制:1 s 内存限制:256 MB

【题目描述】

一天机房的夜晚,无数人在MC里奋斗着。。。

大家都知道矿产对于MC来说是多么的重要,但由于矿越挖越少,勇士们不得不跑到更远的地方挖矿,但这样路途上就会花费相当大的时间,导致挖矿效率低下。

cjj提议修一条铁路,大家一致同意。

大家都被CH分配了一些任务:

zjmfrank2012负责绘制出一个矿道地图,这个地图包括家(当然这也是一个矿,毕竟不把家掏空我们是不会走的),和无数个矿,所以大家应该可以想出这是一个无向无环图,也就是一棵树。

Digital_T和cstdio负责铺铁路。。所以这里没他们什么事,两位可以劳作去了。

这个时候song526210932和RMB突然发现有的矿道会刷怪,并且怪的数量会发生变化。作为采矿主力,他们想知道从一个矿到另一个矿的路上哪一段会最困难。。。(困难值用zjm的死亡次数表示)。

【输入格式】

输入文件的第一行有一个整数N,代表矿的数量。矿的编号是1到N。

接下来N-1行每行有三个整数a,b,c,代表第i号矿和第j号矿之间有一条路,在初始时这条路的困难值为c。

接下来有若干行,每行是“CHANGE i ti”或者“QUERY a b”,前者代表把第i条路(路按所给顺序从1到M编号)的困难值修改为ti,后者代表查询a到b所经过的道路中的最大困难值。

输入数据以一行“DONE”结束。

【输出格式】

对每个“QUERY”操作,输出一行一个正整数,即最大困难值。

【样例输入】

3

1 2 1

2 3 2

QUERY 1 2

CHANGE 1 3

QUERY 1 2

DONE

【样例输出】

1

3

【提示】

对于60%的数据,1<=N<=50

对于100%的数据,1<=N<=10000,1<=c<=1000000,1<=操作次数<=100000

【来源】

由GDFRWMY 改编自SPOJ 375 QTREE

数据by cstdio

题解:

直接LCT维护最大值即可。。。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10010
struct node
{
int left,right,val;
}tree[2*MAXN];
int father[2*MAXN],rev[2*MAXN],mx[2*MAXN],Stack[2*MAXN];
int read()
{
int s=0,fh=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
return s*fh;
}
int isroot(int x)
{
return tree[father[x]].left!=x&&tree[father[x]].right!=x;
}
void pushdown(int x)
{
int l=tree[x].left,r=tree[x].right;
if(rev[x]!=0)
{
rev[x]^=1;rev[l]^=1;rev[r]^=1;
swap(tree[x].left,tree[x].right);
}
}
void pushup(int x)
{
int l=tree[x].left,r=tree[x].right;
mx[x]=x;
if(tree[mx[l]].val>tree[mx[x]].val)mx[x]=mx[l];
if(tree[mx[r]].val>tree[mx[x]].val)mx[x]=mx[r];
}
void rotate(int x)
{
int y=father[x],z=father[y];
if(!isroot(y))
{
if(tree[z].left==y)tree[z].left=x;
else tree[z].right=x;
}
if(tree[y].left==x)
{
father[x]=z;father[y]=x;tree[y].left=tree[x].right;tree[x].right=y;father[tree[y].left]=y;
}
else
{
father[x]=z;father[y]=x;tree[y].right=tree[x].left;tree[x].left=y;father[tree[y].right]=y;
}
pushup(y);pushup(x);
}
void splay(int x)
{
int top=0,i,y,z;Stack[++top]=x;
for(i=x;!isroot(i);i=father[i])Stack[++top]=father[i];
for(i=top;i>=1;i--)pushdown(Stack[i]);
while(!isroot(x))
{
y=father[x];z=father[y];
if(!isroot(y))
{
if((tree[y].left==x)^(tree[z].left==y))rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
int last=0;
while(x!=0)
{
splay(x);
tree[x].right=last;pushup(x);
last=x;x=father[x];
}
}
void makeroot(int x)
{
access(x);splay(x);rev[x]^=1;
}
void link(int u,int v)
{
makeroot(u);father[u]=v;splay(u);
}
void cut(int u,int v)
{
makeroot(u);access(v);splay(v);father[u]=tree[v].left=0;
}
int findroot(int x)
{
access(x);splay(x);
while(tree[x].left!=0)x=tree[x].left;
return x;
}
int main()
{
freopen("qtree.in","r",stdin);
freopen("qtree.out","w",stdout);
int n,i,bb,ee,vv,a,b;
char fh[8];
n=read();
memset(mx,0,sizeof(mx));//瀛樻渶澶у€肩殑缂栧彿.
for(i=1;i<=n;i++)mx[i]=i;
for(i=1;i<n;i++)
{
bb=read();ee=read();vv=read();
tree[n+i].val=vv;
link(bb,n+i);link(ee,n+i);
}
while(1)
{
scanf("\n%s",fh);
if(fh[0]=='D')break;
if(fh[0]=='Q')
{
a=read();b=read();
makeroot(a);access(b);splay(b);
printf("%d\n",tree[mx[b]].val);
}
else
{
a=read();b=read();
makeroot(n+a);tree[n+a].val=b;
}
}
fclose(stdin);
fclose(stdout);
return 0;
}


View Code
树链剖分。。。此坑未填。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: