2856. [洛谷U14475]部落冲突

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

【题目描述】

在一个叫做Travian的世界里,生活着各个大大小小的部落。其中最为强大的是罗马、高卢和日耳曼。他们之间为了争夺资源和土地,进行了无数次的战斗。期间诞生了众多家喻户晓的英雄人物,也留下了许多可歌可泣的动人故事。

其中,在大大小小的部落之间,会有一些道路相连,这些道路是Travian世界里的重要枢纽,简单起见,你可以把这些部落与部落之间相连的道路看作一颗树,可见每条道路对于Travian世界的重要程度。有了这些道路,建筑工人就可以通过这些道路进行友好外交啦。

然而,事情并不会像想象的那样美好,由于资源的匮乏,相邻的部落(由一条道路相连的部落)之间经常会发生大大小小的冲突事件,更有甚者,会升级为部落之间的大型战争。

为了避免误伤,每当两个相邻的部落之间发生大型战争之时,这两个部落间的道路是不允许通行的,对于一些强大的部落,甚至能与多个相邻的部落同时开战,同样的,这些战争地带的道路十分危险,是不可通行的。

天下之势,分久必合,当两个部落经历了不打不相识的苦战之后,他们可以签订停战协议(暂时停战,以后依旧可能再次开战),这样,两个部落之间的道路又会重新恢复为可通行状态,建筑工人们又可以经过此地购买最新的大本营设计图纸来强大自己的部落了。

为了简单起见,我们把各大战争事件按发起的时间顺序依次编号(最先发起的战争编号就为 1,第二次战争编号就为 2,以此类推),当两个部落停战之时,则会直接告诉你这场战争的编号,然后这场战争就载入了史册,不复存在了,当然,这并不会影响到其他战争的编号。

建筑工人十分讨厌战争,因为战争,想从一个部落到另一个部落进行友好交流的建筑工人可能就此白跑一趟。所以,在他们出发之前,都会向你问问能不能到达他们想去的部落。

【输入格式】

第一行两个数 n 和 m, n 代表了一共有 n 个部落,m 代表了以上三种事件发生的总数

接下来的 n - 1行,每行两个数 p , q,代表了第 p 个部落与第 q个部落之间有一条道路相连

接下来的 m 行,每行表示一件事,详见题目描述

【输出格式】

每行一个“Yes”或者“No”,表示从第 p个部落出发的建筑工人能否到达第 q个部落

【样例输入】

5 9

1 2

2 3

3 4

4 5

Q 1 4

C 2 1

C 4 3

Q 3 1

Q 1 5

U 1

U 2

C 4 3

Q 3 4

【样例输出】

Yes

No

No

No

【提示】

对于30%的数据 1<=n,m<=6000

对于另30%的数据,保证部落之间的地理关系是一条链,且 i 与 i + 1 之间有一条道路

对于另30%的数据,1<=n,m<=100000

对于100%的数据,1<=n,m<=300000

【来源】

NOIP 模拟赛 by WISCO信息组

#include<iostream>
#include<cstdio>
#define maxn 300010
using namespace std;
int n,m,num,head[maxn],s[maxn],t[maxn],cnt,fa[maxn],dep[maxn],edge[maxn];
int son[maxn],top[maxn],sz[maxn];
struct node{
int to,pre,v;
}e[maxn*];
void Insert(int from,int to){
e[++num].to=to;
e[num].pre=head[from];
head[from]=num;
}
char ch[];
void dfs(int now,int father){
fa[now]=father;
dep[now]=dep[father]+;
sz[now]=;
for(int i=head[now];i;i=e[i].pre){
int to=e[i].to;
if(to==father)continue;
dfs(to,now);
sz[now]+=sz[to];
edge[to]=i;
if(!son[now]||sz[son[now]]<sz[to])son[now]=to;
}
}
void dfs2(int now,int father){
top[now]=father;
if(son[now])dfs2(son[now],father);
for(int i=head[now];i;i=e[i].pre){
int to=e[i].to;
if(to==son[now]||to==fa[now])continue;
dfs2(to,to);
}
}
int qlca(int a,int b){
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]])swap(a,b);
a=fa[top[a]];
}
if(dep[a]>dep[b])swap(a,b);
return a;
}
void change(int a,int b,int v){
int lca=qlca(a,b);
while(){
if(a==lca)break;
e[edge[a]].v+=v;
a=fa[a];
}
while(){
if(b==lca)break;
e[edge[b]].v+=v;
b=fa[b];
}
}
int query(int a,int b){
int res=;
int lca=qlca(a,b);
while(){
if(a==lca)break;
res=max(res,e[edge[a]].v);
a=fa[a];
}
while(){
if(b==lca)break;
res=max(res,e[edge[b]].v);
b=fa[b];
}
return res;
}
int main(){
// freopen("Cola.txt","r",stdin);
freopen("lct.in","r",stdin);freopen("lct.out","w",stdout); scanf("%d%d",&n,&m);
int x,y,z;
for(int i=;i<n;i++){
scanf("%d%d",&x,&y);
Insert(x,y);Insert(y,x);
}
dfs(,);
dfs2(,);
for(int i=;i<=m;i++){
scanf("%s",ch);
if(ch[]=='Q'){
scanf("%d%d",&x,&y);
int flag=query(x,y);
if(flag)puts("No");
else puts("Yes");
}
if(ch[]=='C'){
scanf("%d%d",&x,&y);
cnt++;s[cnt]=x;t[cnt]=y;
change(x,y,);
}
if(ch[]=='U'){
scanf("%d",&z);
x=s[z];y=t[z];
change(x,y,-);
}
}
return ;
}

95分 暴力

/*
树剖维护树上的两种操作:
1.修改两点之间所有边的边权
2.询问两点之间边权总和是否为0
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
inline int read(){
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
const int maxn=;
int n,m;
struct ww{int u,v;}war[maxn];
int wartot;
vector<int>t[maxn];
int tot,sz[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn],id[maxn],pre[maxn];
inline void dfs1(int u,int f,int d){
sz[u]=;dep[u]=d;fa[u]=f;
int len=t[u].size();
for(int i=;i<len;i++){
int v=t[u][i];
if(v==f)continue;
dfs1(v,u,d+);
sz[u]+=sz[v];
if(!son[u]||sz[son[u]]<sz[v])son[u]=v;
}
}
inline void dfs2(int u,int tou){
top[u]=tou;id[u]=++tot;pre[tot]=u;
if(!son[u])return;
dfs2(son[u],tou);
int len=t[u].size();
for(int i=;i<len;i++){
int v=t[u][i];
if(v!=fa[u]&&v!=son[u])dfs2(v,v);
}
}
int sum[maxn<<];
inline void change(int o,int l,int r,int nl,int nr,int v){
if(l>=nl&&r<=nr){
sum[o]+=v;
return;
}
int m=(l+r)>>,ls=o<<,rs=ls|;
if(m>=nl)change(ls,l,m,nl,nr,v);
if(m<nr)change(rs,m+,r,nl,nr,v);
sum[o]=sum[ls]+sum[rs];
}
inline int find(int o,int l,int r,int nl,int nr){
if(l>=nl&&r<=nr)return sum[o];
int m=(l+r)>>,ls=o<<,rs=ls|;
int ans=;
if(m>=nl)ans+=find(ls,l,m,nl,nr);
if(m<nr)ans+=find(rs,m+,r,nl,nr);
return ans;
}
inline void ok(int x,int y){
int u=top[x],v=top[y];
int ans=;
while(u!=v){
if(dep[u]<dep[v])swap(u,v),swap(x,y);
ans+=find(,,tot,id[u],id[x]);
x=fa[u];u=top[x];
}
if(dep[x]>dep[y])swap(x,y);
if(x!=y)//以边树剖时加特判。
ans+=find(,,tot,id[son[x]],id[y]);
if(ans)puts("No");
else puts("Yes");
}
int main(){
freopen("lct.in","r",stdin);
freopen("lct.out","w",stdout);
n=read();m=read();
for(int i=;i<n;i++){
int u=read(),v=read();
t[u].push_back(v);
t[v].push_back(u);
}
dfs1(,,);
dfs2(,);
for(int i=;i<=m;i++){
char c=getchar();
while(c!='Q'&&c!='C'&&c!='U')c=getchar();
if(c=='Q'){
int x=read(),y=read();
ok(x,y);
}
if(c=='C'){
int ru=;
war[++wartot].u=read(),war[wartot].v=read();
int to;
if(war[wartot].u>war[wartot].v)to=war[wartot].u;
else to=war[wartot].v;
change(,,tot,id[to],id[to],ru);
}
if(c=='U'){
int ru=-;
int x=read();
int to;
if(war[x].u>war[x].v)to=war[x].u;
else to=war[x].v;
change(,,tot,id[to],id[to],ru);
}
}
return ;
}

100分 树剖

Cogs 2856. [洛谷U14475]部落冲突的更多相关文章

  1. 洛谷 U14475 部落冲突 【比赛】 【树链剖分 + 线段树】

    题目背景 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多 ...

  2. 洛谷P3950 部落冲突(LCT)

    洛谷题目传送门 最无脑LCT题解,Dalao们的各种算法都比这个好多啦... 唯一的好处就是只管码代码就好了 开战cut,停战link,询问findroot判连通性 太无脑,应该不用打注释了.常数大就 ...

  3. 洛谷P3950 部落冲突 [LCT]

    题目传送门 部落冲突 格式难调,体面就不放了. 分析: julao们应该都看得出来就是个$LCT$板子,战争就$cut$,结束就$link$,询问就$find$.没了... 太久没打$LCT$,然后发 ...

  4. 洛谷 P3950 部落冲突 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例1 输出样例1 输入样例2 输出样例2 输入样例3 输出样例3 说明 思路 AC代码 总结 题面 题目链接 P3 ...

  5. 【刷题】洛谷 P3950 部落冲突

    题目背景 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多 ...

  6. [洛谷P3950]部落冲突

    题目大意:给你一棵树,有$3$个操作: $Q\;p\;q:$询问$p,q$是否连通 $C\;p\;q:$把$p->q$这条边割断 $U\;x:$恢复第$x$次操作二 题解:可以在割断时把这条边赋 ...

  7. 洛谷:P3950 部落冲突

    原题地址:https://www.luogu.org/problemnew/show/P3950 题目简述 给定一棵树,每次给定一个操作,有如下两种: 将某条边染黑 2.询问给定的u,v两点间是否有边 ...

  8. [题解] 洛谷P3950 部落冲突

    传送门 拿到题目,一看 裸LCT (其实是我懒得打,splay又臭又长) 首先,这道题的意思就是删掉一些边 所以常规操作 点权转边权 之后对于战争操作,在对应的边上+1 对于和平操作,在对应的边上-1 ...

  9. 洛谷——P1692 部落卫队

    题目描述 原始部落byteland中的居民们为了争夺有限的资源,经常发生冲突.几乎每个居民都有他的仇敌.部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入伍,并保证队伍中任何2 个 ...

随机推荐

  1. 分享知识-快乐自己:Spring整合定时器

    前期工作:(引入相关 JAR ) <spring.quartz>1.8.4</spring.quartz> <!--spring 定时--> <depende ...

  2. yahoo的30条优化规则

    1.尽量减少HTTP请求次数 终端用户响应的时间中,有80%用于下载各项内容.这部分时间包括下载页面中的图像.样式表.脚本.Flash等.通过减少页面中的元素可以减少HTTP请求的次数.这是提高网页速 ...

  3. FFmpeg 基本用法--此文转载,作为笔记

    v  容器(Container) v  容器就是一种文件(封装)格式,比如flv.mkv.ts.mp4.rmvb.avi等.包含下面5种流以及文件头信息. v  流(Stream) v  是一种视频数 ...

  4. Winform程序实现多显示屏、多屏幕显示的2种方法

    这篇文章主要介绍了Winform窗口实现多显示屏显示的2种方法,本文直接给出了实现代码,并对其中的一些重要参数做了解释,需要的朋友可以参考下. 一台主机连接了2台显示器(2个显卡),要求一个程序的两个 ...

  5. MongoDB优化之二:常见优化方法

    四个方面进行 cpu/io 方面的优化处理: 1.集群架构上进行读写分离.所有查询优先考虑在从库上读取,写操作在主库上执行.避免主库混合读写压力过大,也减少主库上读写记录的锁冲突. connectio ...

  6. Ruby中print、p、puts的区别

    三个方法的作用都是将一个字符串打印到控制台  比较项目  puts  print p   换行符 末尾添加换行符  末尾不加换行符  末尾添加换行符  非字符串对象的输出  调用该对象的to_s方法 ...

  7. <正则吃饺子>:关于java中垃圾回收技术的简单学习总结

    知识介绍来自网络,后面会根据继续学习进行补充和适当的修改,谢谢!原文地址:http://www.importnew.com/26821.html#comment-578355 java中的垃圾回收机制 ...

  8. linux日常管理-rsync格式

    rsync支持网络到本地,本地到网络,本地到本地拷贝数据,支持增量拷贝.用作备份. man rsync rsync的两大用法.一种是通过shell,一种是deamon. shell  pull远程机器 ...

  9. mouseenter与mouseover的区别

    mouseover 事件:只有在鼠标指针穿过被选元素时,才会触发. mouseover 事件:鼠标指针穿过任何子元素,都会触发. 请看例子的演示.

  10. ViewPage+Fragment(仿微信切换带通知)

    第一步 : 布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <Li ...