Cogs 2856. [洛谷U14475]部落冲突
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]部落冲突的更多相关文章
- 洛谷 U14475 部落冲突 【比赛】  【树链剖分 + 线段树】
		题目背景 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多 ... 
- 洛谷P3950 部落冲突(LCT)
		洛谷题目传送门 最无脑LCT题解,Dalao们的各种算法都比这个好多啦... 唯一的好处就是只管码代码就好了 开战cut,停战link,询问findroot判连通性 太无脑,应该不用打注释了.常数大就 ... 
- 洛谷P3950 部落冲突 [LCT]
		题目传送门 部落冲突 格式难调,体面就不放了. 分析: julao们应该都看得出来就是个$LCT$板子,战争就$cut$,结束就$link$,询问就$find$.没了... 太久没打$LCT$,然后发 ... 
- 洛谷 P3950 部落冲突 树链剖分
		目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例1 输出样例1 输入样例2 输出样例2 输入样例3 输出样例3 说明 思路 AC代码 总结 题面 题目链接 P3 ... 
- 【刷题】洛谷 P3950 部落冲突
		题目背景 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多 ... 
- [洛谷P3950]部落冲突
		题目大意:给你一棵树,有$3$个操作: $Q\;p\;q:$询问$p,q$是否连通 $C\;p\;q:$把$p->q$这条边割断 $U\;x:$恢复第$x$次操作二 题解:可以在割断时把这条边赋 ... 
- 洛谷:P3950 部落冲突
		原题地址:https://www.luogu.org/problemnew/show/P3950 题目简述 给定一棵树,每次给定一个操作,有如下两种: 将某条边染黑 2.询问给定的u,v两点间是否有边 ... 
- [题解] 洛谷P3950 部落冲突
		传送门 拿到题目,一看 裸LCT (其实是我懒得打,splay又臭又长) 首先,这道题的意思就是删掉一些边 所以常规操作 点权转边权 之后对于战争操作,在对应的边上+1 对于和平操作,在对应的边上-1 ... 
- 洛谷——P1692 部落卫队
		题目描述 原始部落byteland中的居民们为了争夺有限的资源,经常发生冲突.几乎每个居民都有他的仇敌.部落酋长为了组织一支保卫部落的队伍,希望从部落的居民中选出最多的居民入伍,并保证队伍中任何2 个 ... 
随机推荐
- Java之泛型浅解
			我觉得学习一个东西,首先得从概念上明白它大概是什么? “泛型”就是“参数化类型”,也就是是把类型当成了一种参数.之前我们看到得函数方法比如: public long add(int num1,int ... 
- 2018.5.8  Project  review
			1 .product introduced A. Function requirement (customer) The product function is control the 1KW and ... 
- 【LeetCode】014. Longest Common Prefix
			Write a function to find the longest common prefix string amongst an array of strings. 题解: 简单的暴力遍历解决 ... 
- delete操作符
			delete操作符通常用来删除对象的属性: Js代码 var o = { x: 1 }; delete o.x; // true o.x; // undefined 而不是一般的变量: Js代 ... 
- Maven: 自动远程部署
			1. 在settings.xml中的Servers节点中增加Server的登录信息: <server> <id>deploy_server_65</id> < ... 
- 如何得到DataTable的列名
			foreach (DataColumn dc in dtfood.Columns) { string lm = dc.ColumnName; } 
- CCS V5 使用教程三:程序调试
			官网教程 新建调试工程 输入以下源码: #include <stdio.h> #include <c6x.h> ]; void main(void) { unsigned ; ... 
- java代码for循环+缓冲流类
			总结:这个结果竟然是对的.我错了. package com.da; //创建一个String对象的数组,然后执行读取文本,把文本每一行存入数组,它将读取到100行 //或直接到你按”stop“才停止, ... 
- 【转载】ruby 中数组函数示例(1)(转)
			函数名称 说明 示例 & 数组与,返回两数组的交集 [1,2] & [2,3] =>[2] * 复制数组n次 [1,2]*2 => [1,2,1, ... 
- mysql查询语句例题
			1.一条SQL语句查询两表中两个字段 首先描述问题,student表中有字段startID,endID.garde表中的ID需要对应student表中的startID或者student表中的endID ... 
