BZOJ P2157 旅游
题目大意:
维护一棵树,每条边有边权,支持下列操作:
1.修改某条边的边权
2.将某条路经上的边权取反
3.询问某条路经上的和
4.询问某条路经上的最大值
5.询问某条路经上的最小值
--by BZOJ;
http://www.lydsy.com/JudgeOnline/problem.php?id=2157
有关树链剖分的详解,见:树链剖分
链剖模板,代码长了点,主要是线段树部分操作太多,注意可以把边权搞到点上;
代码如下:
#include<cstdio>
#define INF 0x3fffffff
using namespace std;
struct ss{
int to,next,dis;
}x[];
int first[],num;
int size[];//子树和//
int hway[];//重边//
int rank[];//点在line_tree中的位置//
int rankl[];//边所对点在line_tree中的位置//
int dis[];//点权 //
int top[];//重链顶 //
int dep[];//深度 //
int fa[];//父亲//
int a[];//line_tree的原line序列//
int ltre[];
int max[];
int min[];
int lz[];
int n,m,L,R,X,W;
void swap(int&,int&);
void build(int ,int ,int );
void dfs_1(int );
void dfs_2(int ,int );
void up(int );
void down(int ,int ,int );
void builtre(int ,int ,int );
void work(int );
int wor_(int ,int );
void chan1(int ,int ,int );
void chan2(int ,int ,int );
int sum(int ,int ,int );
int Max(int ,int ,int );
int Min(int ,int ,int );
int main()
{
int i,j,k,l;
char s[];
scanf("%d",&n);
for(i=;i<=n-;i++)
hway[i]=i;
for(i=;i<=n-;i++){
scanf("%d%d%d",&j,&k,&l);
build(j,k,l);
build(k,j,l);
}
dep[]=;
dfs_1();
num=;
dfs_2(,);
num=;
builtre(,n,);
scanf("%d",&m);
for(i=;i<=m;i++){
scanf("%s",s);
scanf("%d%d",&L,&R);
if(s[]!='\0')s[]=s[];
if(s[]=='C')X=rankl[L],W=R;
switch (s[]){
case 'C': chan1(,n,);break;//C
case 'N': work();break;//N
case 'U': work();break;//NUM
case 'A': work();break;//MAX
case 'I': work();break;//MIN
}
}
}
void swap(int &a,int &b){
int i;
i=a;a=b;b=i;
}
void build(int f,int t,int l){
x[++num].next=first[f];
x[num].dis=l;
x[num].to=t;
first[f]=num;
}
void dfs_1(int now){
int j=first[now];
while(j){
if(!dep[x[j].to]){
dis[x[j].to]=x[j].dis;
dep[x[j].to]=dep[now]+;
fa[x[j].to]=now;
dfs_1(x[j].to);
size[now]+=size[x[j].to];
if(hway[now]==now||size[x[j].to]>size[hway[now]])
hway[now]=x[j].to;
}
j=x[j].next;
}
size[now]++;
}
void dfs_2(int now,int to_nu){
int j=first[now];
top[now]=to_nu;
rank[now]=++num;
a[num]=now;
if(hway[now]!=now)
dfs_2(hway[now],to_nu);
while(j){
if(dep[x[j].to]>dep[now]&&x[j].to!=hway[now])
rankl[(j+)>>]=num+,dfs_2(x[j].to,x[j].to);
if(x[j].to==hway[now])
rankl[(j+)>>]=rank[hway[now]];
j=x[j].next;
}
}
void up(int nu){
ltre[nu]=ltre[nu<<]+ltre[nu<<|];
max[nu]=max[nu<<]>max[nu<<|]?max[nu<<]:max[nu<<|];
min[nu]=min[nu<<]<min[nu<<|]?min[nu<<]:min[nu<<|];
}
void down(int l,int r,int nu){
if(!lz[nu]) return;
lz[nu<<]^=;lz[nu<<|]^=;
swap(max[nu<<],min[nu<<]);
max[nu<<]=-max[nu<<]; min[nu<<]=-min[nu<<];
ltre[nu<<]=-ltre[nu<<];
swap(max[nu<<|],min[nu<<|]);
max[nu<<|]=-max[nu<<|]; min[nu<<|]=-min[nu<<|];
ltre[nu<<|]=-ltre[nu<<|];
lz[nu]=;
}
void builtre(int l,int r,int nu){
if(l==r){
max[nu]=min[nu]=ltre[nu]=dis[a[++num]];
if(a[num]==){
max[nu]=-INF;
min[nu]=INF;
}
return;
}
int mid=(l+r)>>;
builtre(l,mid,nu<<);
builtre(mid+,r,nu<<|);
up(nu);
}
void work(int x){
int ans=;
if(x==)ans=-INF;
if(x==)ans=INF;
int u=L,v=R;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])
L=rank[top[v]],R=rank[v],v=fa[top[v]];
else
L=rank[top[u]],R=rank[u],u=fa[top[u]];
ans=wor_(ans,x);
}
if(u!=v){
if(dep[u]>dep[v])
swap(u,v);
u=hway[u];
L=rank[u];R=rank[v];
ans=wor_(ans,x);
}
if(x>=)
printf("%d\n",ans);
}
int wor_(int ans,int x){
int i;
if(x==)
chan2(,n,);
if(x==)
ans+=sum(,n,);
if(x==){
i=Max(,n,);ans=ans>i?ans:i;}
if(x==){
i=Min(,n,);ans=ans<i?ans:i;}
return ans;
}
void chan1(int l,int r,int nu){
if(l==r){
max[nu]=min[nu]=ltre[nu]=W ;
return;
}
int mid=(l+r)>>;
down(l,r,nu);
if(X<=mid)
chan1(l,mid,nu<<);
if(X>mid)
chan1(mid+,r,nu<<|);
up(nu);
}
void chan2(int l,int r,int nu){
if(L<=l&&r<=R){
swap(max[nu],min[nu]);
max[nu]=-max[nu];
min[nu]=-min[nu];
ltre[nu]=-ltre[nu];
lz[nu]^=;
return ;
}
down(l,r,nu);
int mid=(l+r)>>;
if(L<=mid)
chan2(l,mid,nu<<);
if(R>mid)
chan2(mid+,r,nu<<|);
up(nu);
}
int sum(int l,int r,int nu){
if(L<=l&&r<=R)
return ltre[nu];
down(l,r,nu);
int mid=(l+r)>>,re=;
if(L<=mid)
re+=sum(l,mid,nu<<);
if(R>mid)
re+=sum(mid+,r,nu<<|);
return re;
}
int Max(int l,int r,int nu){
if(L<=l&&r<=R)
return max[nu];
down(l,r,nu);
int mid=(l+r)>>,lm=-INF,rm=-INF;
if(L<=mid)
lm=Max(l,mid,nu<<);
if(R>mid)
rm=Max(mid+,r,nu<<|);
if(lm>=rm)
return lm;
return rm;
}
int Min(int l,int r,int nu){
if(L<=l&&r<=R)
return min[nu];
down(l,r,nu);
int mid=(l+r)>>,lm=INF,rm=INF;
if(L<=mid)
lm=Min(l,mid,nu<<);
if(R>mid)
rm=Min(mid+,r,nu<<|);
if(lm<=rm)
return lm;
return rm;
}
祝AC哟;
BZOJ P2157 旅游的更多相关文章
- BZOJ 2157: 旅游( 树链剖分 )
树链剖分.. 样例太大了根本没法调...顺便把数据生成器放上来 -------------------------------------------------------------------- ...
- bzoj 2157: 旅游 (LCT 边权)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2157 题面; 2157: 旅游 Time Limit: 10 Sec Memory Lim ...
- 【刷题】BZOJ 2157 旅游
Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间 ...
- BZOJ 2157: 旅游
2157: 旅游 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1347 Solved: 619[Submit][Status][Discuss] ...
- bzoj [POI2007]旅游景点atr 状态压缩+Dij
[POI2007]旅游景点atr Time Limit: 30 Sec Memory Limit: 357 MBSubmit: 2258 Solved: 595[Submit][Status][D ...
- bzoj 2657 旅游
Written with StackEdit. Description 到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~ 经过一番抉择,两人决定将\(T\)国作为他们 ...
- BZOJ 2157: 旅游 (2017.7.21 6:30-2017.7.21 15:38 今日第一题。。)
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1754 Solved: 765 Description Ray 乐忠于旅游,这次他来到了T 城.T ...
- BZOJ 3999 旅游
.......好长啊. #include<iostream> #include<cstdio> #include<cstring> #include<algo ...
- BZOJ 2157 旅游(动态树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2157 [题目大意] 支持修改边,链上查询最大值最小值总和,以及链上求相反数 [题解] ...
随机推荐
- java_I/O字符流
I/O流(Stream) INPUT:输入流,从文件里读OUPUT:输出流,写内容到文件 IO流分为:字符流和字节流 字符流:处理纯文本文件. 字节流:处理可以所有文件. 字符输出流测试: @Test ...
- mysql 与sqlser group by
mysql select * ,count(1) from simccbillm18 group by MonthNum; SqlSer select col1,col2 from table g ...
- TX2 刷机时遇到Parsing board information failed
因为之前调试I2C时,修改了EEPROM Layout,所以,在刷机时遇到此问题. 解决办法是按照此文档中的介绍来修改布局. 实际操作时,我拿了一块正常的TX2,按照指令: sudo i2cdump ...
- 在Eclipse平台中,搭建SpringBoot开发环境
1.查看eclipse版本号,Help->About Eclipse IDE 2.下载对应版本的STS插件 下载地址:https://spring.io/tools3/sts/all(注意版本对 ...
- OI中一些常见实用的套路【更新中】
数据结构 在维护树上路径时,如果只是点的独立的加减,可以考虑用括号序来维护(拆成两部分) 需要求树上很多路径中k近/距离和 一类,考虑点分治/在点分树上解决. 子树求和可以转化为DFS序上区间求和 树 ...
- Java 并发编程——Callable+Future+FutureTask
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- js中请求数据的$post和$ajax区别(同步和异步问题)
$.post和$.Ajax都为页面上向后台发送请求,请求数据 1.post 因为post默认为异步请求,可是有时候我们会发现,本来要求请求马上出现,可是异步会导致后面突然再执行,这样就出很多问题 2. ...
- Oracle 汉字转拼音触发器
--函数GetHzFullPY(string)用于获取汉字字符串的拼音 --select GetHzFullPY('中华人民共和国') from dual; --返回:ZhongHuaRenMinGo ...
- WebLogic 数据源密码加密
先启动域:
- JAVA练手--数组
//数组 public static void main(String[] args) { //1. 数组排序和查找 { int[] intA = {5, 4, 2, 3, 1}; String[] ...