您的位置:首页 > 其它

BZOJ 2157: 旅游 树链剖分

2017-08-16 15:01 441 查看

2157: 旅游

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1816  Solved: 794

[Submit][Status][Discuss]

Description

Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray
看待同一座桥的心情也会发生改变。现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。

Input

输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0...N − 1。接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。桥的编号为1...N − 1。|w| <= 1000。输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。接下来有M 行,每行描述了一个操作,操作有如下五种形式: C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。 N u v,表示Ray
对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。 SUM u v,表示询问从景点u 到v 所获得的总愉悦度。 MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。 MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。

Output

对于每一个询问(操作S、MAX 和MIN),输出答案。

Sample Input

3

0 1 1

1 2 2

8

SUM 0 2

MAX 0 2

N 0 1

SUM 0 2

MIN 0 2

C 1 3

SUM 0 2

MAX 0 2

Sample Output

3

2

1

-1

5

3

HINT

一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。

大链剖

把边权下放到点权竟然写着写着就忘了

结果一顿狂调

调了几个小时才发现错误。。。

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=20100,inf=0X3f3f3f3f;

int n;

int ecnt,last
;
struct EDGE{int fr,to,nt,val;}e[N<<1];
inline void add(int u,int v,int val)
{e[++ecnt]=(EDGE){u,v,last[u],val};last[u]=ecnt;}

int V
,d
,fa
,size
;

void dfs1(int u)
{
d[u]=d[fa[u]]+1;size[u]=1;
for(int i=last[u];i;i=e[i].nt)
{
if(e[i].to==fa[u])continue;
V[e[i].to]=e[i].val;fa[e[i].to]=u;
dfs1(e[i].to);size[u]+=size[e[i].to];
}
}

int top
,dfn
,cnt;

void dfs2(int u,int tp)
{
int k=0;top[u]=tp;dfn[u]=++cnt;
for(int i=last[u];i;i=e[i].nt)
{
if(e[i].to==fa[u])continue;
if(size[e[i].to]>size[k])k=e[i].to;
}
if(!k)return ;
dfs2(k,tp);
for(int i=last[u];i;i=e[i].nt)
{
if(e[i].to==fa[u]||e[i].to==k)continue;
dfs2(e[i].to,e[i].to);
}
}

struct seg_tree{int mx,mn,sum;bool mark;}tr[N<<2];

inline void pushup(int k)
{
tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
tr[k].mn=min(tr[k<<1].mn,tr[k<<1|1].mn);
tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
}

inline void pushdown(int k)
{
if(tr[k].mark)
{
tr[k].mark=0;
tr[k<<1].mark^=1;tr[k<<1|1].mark^=1;
swap(tr[k<<1].mn,tr[k<<1].mx);
swap(tr[k<<1|1].mn,tr[k<<1|1].mx);
tr[k<<1].mn*=-1;tr[k<<1].mx*=-1;
tr[k<<1|1].mn*=-1;tr[k<<1|1].mx*=-1;
tr[k<<1].sum*=-1;tr[k<<1|1].sum*=-1;
}
}

void modify(int k,int l,int r,int x,int val)
{
if(l==r){tr[k].mark=0;tr[k].sum=tr[k].mn=tr[k].mx=val;return ;}
int mid=(l+r)>>1;pushdown(k);
x<=mid?modify(k<<1,l,mid,x,val):modify(k<<1|1,mid+1,r,x,val);
pushup(k);
}

int query_mx(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)return tr[k].mx;
int mid=(l+r)>>1;pushdown(k);
if(x>mid)return query_mx(k<<1|1,mid+1,r,x,y);
if(y<=mid)return query_mx(k<<1,l,mid,x,y);
return max(query_mx(k<<1|1,mid+1,r,x,y),query_mx(k<<1,l,mid,x,y));
}

int query_mn(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)return tr[k].mn;
int mid=(l+r)>>1;pushdown(k);
if(x>mid)return query_mn(k<<1|1,mid+1,r,x,y);
if(y<=mid)return query_mn(k<<1,l,mid,x,y);
return min(query_mn(k<<1|1,mid+1,r,x,y),query_mn(k<<1,l,mid,x,y));
}

int query_sum(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)return tr[k].sum;
int mid=(l+r)>>1;pushdown(k);
if(x>mid)return query_sum(k<<1|1,mid+1,r,x,y);
else if(y<=mid)return query_sum(k<<1,l,mid,x,y);
else return query_sum(k<<1|1,mid+1,r,x,y)+query_sum(k<<1,l,mid,x,y);
}

void rever(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
tr[k].mark^=1;
swap(tr[k].mx,tr[k].mn);tr[k].sum*=-1;tr[k].mn*=-1;tr[k].mx*=-1;
return ;
}
int mid=(l+r)>>1;pushdown(k);
if(y>mid)rever(k<<1|1,mid+1,r,x,y);
if(x<=mid)rever(k<<1,l,mid,x,y);
pushup(k);
}

void getrever(int u,int v)
{
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
rever(1,1,n,dfn[top[u]],dfn[u]);
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
if(u^v)rever(1,1,n,dfn[v]+1,dfn[u]);
}

int getmx(int u,int v)
{
int res=-inf;
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
res=max(res,query_mx(1,1,n,dfn[top[u]],dfn[u]));
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
if(u^v)res=max(res,query_mx(1,1,n,dfn[v]+1,dfn[u]));
return res;
}

int getmn(int u,int v)
{
int res=inf;
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
res=min(res,query_mn(1,1,n,dfn[top[u]],dfn[u]));
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
if(u^v)res=min(res,query_mn(1,1,n,dfn[v]+1,dfn[u]));
return res;
}

int getsum(int u,int v)
{
int res=0;
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]])swap(u,v);
res+=query_sum(1,1,n,dfn[top[u]],dfn[u]);
u=fa[top[u]];
}
if(d[u]<d[v])swap(u,v);
if(u^v)res+=query_sum(1,1,n,dfn[v]+1,dfn[u]);
return res;
}

int main()
{
n=read();
register int i,u,v,val;
for(i=1;i<n;++i){u=read()+1;v=read()+1;val=read();add(u,v,val);add(v,u,val);}
dfs1(1);dfs2(1,1);
for(i=1;i<=n;++i)modify(1,1,n,dfn[i],V[i]);
int Q=read();char ch[10];
while(Q--)
{
scanf("%s",ch);u=read()+1;v=read()+1;
switch(ch[0])
{
case 'C':u--;v--;d[e[u<<1].fr]>d[e[u<<1].to]?u=e[u<<1].fr:u=e[u<<1].to;modify(1,1,n,dfn[u],v);break;
case 'N':getrever(u,v);break;
case 'S':print(getsum(u,v));puts("");break;
case 'M':ch[1]=='A'?print(getmx(u,v)):print(getmn(u,v));puts("");break;
default:break;
}
}
return 0;
}
/*
3
0 1 1
1 2 2
8
SUM 0 2
MAX 0 2
N 0 1
SUM 0 2
MIN 0 2
C 1 3
SUM 0 2
MAX 0 2

3
2
1
-1
5
3
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: