洛谷 P3950 部落冲突 树链剖分
题面
题目链接
题目描述
在一个叫做Travian的世界里,生活着各个大大小小的部落。其中最为强大的是罗马、高卢和日耳曼。他们之间为了争夺资源和土地,进行了无数次的战斗。期间诞生了众多家喻户晓的英雄人物,也留下了许多可歌可泣的动人故事。
其中,在大大小小的部落之间,会有一些道路相连,这些道路是Travian世界里的重要枢纽,简单起见,你可以把这些部落与部落之间相连的道路看作一颗树,可见每条道路对于Travian世界的重要程度。有了这些道路,建筑工人就可以通过这些道路进行友好外交啦。
然而,事情并不会像想象的那样美好,由于资源的匮乏,相邻的部落(由一条道路相连的部落)之间经常会发生大大小小的冲突事件,更有甚者,会升级为部落之间的大型战争。
为了避免误伤,每当两个相邻的部落之间发生大型战争之时,这两个部落间的道路是不允许通行的,对于一些强大的部落,甚至能与多个相邻的部落同时开战,同样的,这些战争地带的道路十分危险,是不可通行的。
天下之势,分久必合,当两个部落经历了不打不相识的苦战之后,他们可以签订停战协议(暂时停战,以后依旧可能再次开战),这样,两个部落之间的道路又会重新恢复为可通行状态,建筑工人们又可以经过此地购买最新的大本营设计图纸来强大自己的部落了。
为了简单起见,我们把各大战争事件按发起的时间顺序依次编号(最先发起的战争编号就为 1,第二次战争编号就为 2,以此类推),当两个部落停战之时,则会直接告诉你这场战争的编号,然后这场战争就载入了史册,不复存在了,当然,这并不会影响到其他战争的编号。
建筑工人十分讨厌战争,因为战争,想从一个部落到另一个部落进行友好交流的建筑工人可能就此白跑一趟。所以,在他们出发之前,都会向你问问能不能到达他们想去的部落。
简单起见,你就是要处理下面三件事,所有的事件都是按照时间顺序给出的。
- $ (Q p q) $ 从第 $ p $ 个部落出发的建筑工人想知道能否到达第 $ q $ 部落了,你要回答的便是(Yes/No),注意大小写 
- $ (C p q) $ 第 $ p $ 个部落与第 $ q $ 个部落开战了,保证他们一定是相邻的部落,且目前处于停战(未开战)状态 
- $ (U x) $ 第 $ x $ 次发生的战争结束了,它将永远的被载入史册,不复存在(保证这个消息不会告诉你多次) 
输入输出格式
输入格式
第一行两个数 $ n $ 和 $ m , n $ 代表了一共有 $ n $ 个部落, $ m $ 代表了以上三种事件发生的总数
接下来的 $ n-1 $ 行,每行两个数 $ p,q $ ,代表了第 $ p $ 个部落与第 $ q $ 个部落之间有一条道路相连
接下来的 $ m $ 行,每行表示一件事,详见题目描述
输出格式
每行一个“Yes”或者“No”,表示从第 $ p $ 个部落出发的建筑工人能否到达第 $ q $ 个部落
输入输出样例
输入样例1
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
输出样例1
Yes
No
No
No
输入样例2
10 10
1 2
1 3
3 4
3 5
1 6
3 7
1 8
2 9
5 10
C 8 1
Q 6 1
C 2 1
Q 2 10
U 1
C 9 2
C 7 3
U 3
Q 6 7
Q 1 10
输出样例2
Yes
No
No
Yes
输入样例3
20 20
1 2
1 3
2 4
1 5
1 6
4 7
1 8
2 9
5 10
1 11
2 12
7 13
1 14
1 15
11 16
4 17
3 18
18 19
8 20
Q 13 5
C 14 1
C 16 11
U 1
U 2
C 20 8
Q 7 1
C 7 4
Q 17 17
Q 1 6
C 16 11
C 2 1
Q 16 2
U 3
U 5
U 6
C 2 1
C 6 1
C 13 7
C 11 1
输出样例3
Yes
Yes
Yes
Yes
No
说明
对于30%的数据 $ 1 \leq n , m \leq 6000 $
对于另30%的数据,保证部落之间的地理关系是一条链,且 $ i $ 与 $ i+1 $ 之间有一条道路
对于另30%的数据, $ 1 \leq n , m \leq 100000 $
对于100%的数据, $ 1 \leq n , m \leq 300000 $
【时空限制】
1000ms,128MB
思路
原题怎么这么长,还配了一张图。。。
这题意思简化一下就是,每次可以让一条边权值减1或加1,问两点间路径上有没有边权值小于0(大概就这样吧)
其实是好久没写树剖所以来水一道题啦
AC代码
#include<bits/stdc++.h>
const int maxn=300010;
using namespace std;
int n,m;
int tot,to[maxn<<1],nxt[maxn<<1],head[maxn];
int a[maxn];
int fa[maxn],son[maxn],len[maxn],dep[maxn];
int cnt,nid[maxn],top[maxn];
struct SegmentTree
{
    int l,r,sum;
    #define l(a) tree[a].l
    #define r(a) tree[a].r
    #define m(a) ((l(a)+r(a))>>1)
    #define len(a) (r(a)-l(a)+1)
    #define s(a) tree[a].sum
}tree[maxn<<2];
void dfs1(int u,int f,int d)
{
    fa[u]=f;dep[u]=d;len[u]=1;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(v==f) continue;
        dfs1(v,u,d+1);
        len[u]+=len[v];
        if(len[v]>len[son[u]]) son[u]=v;
    }
}
void dfs2(int p,int t)
{
    top[p]=t;
    nid[p]=++cnt;
    if(!son[p]) return;
    dfs2(son[p],t);
    for(int i=head[p];i;i=nxt[i])
    {
        int v=to[i];
        if(v==fa[p] ||v==son[p]) continue;
        dfs2(v,v);
    }
}
void BuildTree(int p,int l,int r)
{
    l(p)=l;r(p)=r;
    if(l==r) return;
    BuildTree(p<<1,l,m(p));
    BuildTree(p<<1|1,m(p)+1,r);
}
void Change(int np,int p)
{
    if(l(np)==r(np))
    {
        s(np)^=1;
        return;
    }
    if(p<=m(np)) Change(np<<1,p);
    else Change(np<<1|1,p);
    s(np)=s(np<<1)+s(np<<1|1);
}
int Ask1(int p,int l,int r)
{
    if(l<=l(p) && r>=r(p)) return s(p);
    int ans=0;
    if(l<=m(p)) ans+=Ask1(p<<1,l,r);//if(ans>0) return ans;
    if(r>m(p)) ans+=Ask1(p<<1|1,l,r);//if(ans>0) return ans;
    return ans;
}
int Ask2(int u,int v)
{
    int ans=0;
    while(top[u]!=top[v])
    {
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans+=Ask1(1,nid[top[u]],nid[u]);
        u=fa[top[u]];
    }
    if(u==v) return ans;
    if(dep[u]>dep[v]) swap(u,v);
    ans+=Ask1(1,nid[u]+1,nid[v]);
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,u,v;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        to[++tot]=v;nxt[tot]=head[u];head[u]=tot;
        to[++tot]=u;nxt[tot]=head[v];head[v]=tot;
    }
    dfs1(1,1,1);
    dfs2(1,1);
    BuildTree(1,1,n);
    cnt=0;
    for(int i=1;i<=m;i++)
    {
        char opt;int x,y;
        cin>>opt;
        if(opt=='Q')
        {
            scanf("%d%d",&x,&y);
            if(Ask2(x,y)) printf("No\n");
            else printf("Yes\n");
        }
        else if(opt=='C')
        {
            scanf("%d%d",&x,&y);
            ++cnt;a[cnt]=(dep[x]>dep[y]? x:y);
            Change(1,nid[a[cnt]]);
        }
        else
        {
            scanf("%d",&x);
            Change(1,nid[a[x]]);
        }
    }
    return 0;
}
总结
这道题不难。但是题中所给的条件一定要用好,比如战争的两点一定相邻。
回顾一下以前的知识点总是好的
洛谷 P3950 部落冲突 树链剖分的更多相关文章
- luogu题解 P3950部落冲突--树链剖分
		题目链接 https://www.luogu.org/problemnew/show/P3950 分析 大佬都用LCT,我太弱只会树链剖分 一个很裸的维护边权树链剖分题.按照套路,对于一条边\(< ... 
- BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分
		欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ... 
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
		题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ... 
- 洛谷:P3950 部落冲突
		原题地址:https://www.luogu.org/problemnew/show/P3950 题目简述 给定一棵树,每次给定一个操作,有如下两种: 将某条边染黑 2.询问给定的u,v两点间是否有边 ... 
- 洛谷P3950 部落冲突 [LCT]
		题目传送门 部落冲突 格式难调,体面就不放了. 分析: julao们应该都看得出来就是个$LCT$板子,战争就$cut$,结束就$link$,询问就$find$.没了... 太久没打$LCT$,然后发 ... 
- 洛谷P3459 [POI2007]MEG-Megalopolis [树链剖分]
		题目传送门 MEG 题目描述 Byteotia has been eventually touched by globalisation, and so has Byteasar the Postma ... 
- 洛谷P3950 部落冲突(LCT)
		洛谷题目传送门 最无脑LCT题解,Dalao们的各种算法都比这个好多啦... 唯一的好处就是只管码代码就好了 开战cut,停战link,询问findroot判连通性 太无脑,应该不用打注释了.常数大就 ... 
- 【刷题】洛谷 P3950 部落冲突
		题目背景 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多 ... 
- 洛谷 P2486 [SDOI2011]染色 树链剖分
		目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ... 
随机推荐
- Nmap扫描原理(上)
			转自:https://blog.csdn.net/qq_34398519/article/details/89055991 Nmap是一款开源免费的网络发现(Network Discovery)和安全 ... 
- Leetcode279. Perfect Squares完全平方数
			给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n.你需要让组成和的完全平方数的个数最少. 示例 1: 输入: n = 12 输出: 3 解释: 12 ... 
- 跟我一起安装vmware
			第一步查看我们的电脑配置 我是windows10,下面的方法是windows10来安装vmware 第二步双击下图文件 (1) 2)弹出如下图,点击下一步即可. (3)一直点击下一步(期间会同意,勾选 ... 
- MySQL8.0.17 - 初探 Clone Plugin
			MySQL8.0.17推出了一个重量级的功能:clone plugin.允许用户可以将当前实例进行本地或者远程的clone.这在某些场景尤其想快速搭建复制备份或者在group replication里 ... 
- c语言学习笔记 - 顺序查找和哨兵查找比较
			今天学习C时用到了顺序查找和哨兵查找,做了一个比较,主要是学习下哨兵查找法 例如在一个数组里查找一个元素,没找到返回-1,找到了则返回这个数组的下标也就是键值. 用循序查找法: void arr_se ... 
- 新手必踩坑之display: inline-block
			今日励志语 往日不可追,来日犹可期,祝大家2019年继往开来 迷之间隙 我们创建一个导航列表,并将其列表 item 设置为 inline-block,主要代码如下: <div class=&qu ... 
- python-基础-面象对象
			1 类和对象 定义类 定义一个类,格式如下: class 类名: 方法列表 demo:定义一个Car类 # 定义类 class Car: # 方法 def getCarInfo(self): prin ... 
- JavaWeb-类加载器-注解-动态代理
			(一)类加载器 1.什么是类加载器,作用是什么? 类加载器就加载字节码文件(.class) 2.类加载器的种类 类加载器有三种,不同类加载器加载不同的 1)BootStrap:引导类加载器:加载都是最 ... 
- 使用powerDesigner绘制类图
			使用powerDesigner绘制类图 因为后面要理清楚spring中类与类之间关系,我们来看看如何使用powerDesigner绘制类图 你要去下载powerDesiger,一路下一步安装好 打开, ... 
- LC327 Count of Range Number
			这一题,我们使用了分治法. 首先看时间复杂度为o(n^2),比较naïve的方法: 使用一个数组sum[],长度为原数组长度+1,每一个元素sum[i]为原数组中index0~i-1之和,显然当sum ... 
