P3950 部落冲突

\(\color{#0066ff}{ 题目描述 }\)

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

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

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

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

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

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

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

简单起见,你就是要处理下面三件事,所有的事件都是按照时间顺序给出的。

1.(\(Q\) \(p\) \(q\))从第 \(p\) 个部落出发的建筑工人想知道能否到达第 \(q\) 个部落了,你要回答的便是(Yes/No),注意大小写

2.(\(C\) \(p\) \(q\))第 \(p\) 个部落与第 \(q\) 个部落开战了,保证他们一定是相邻的部落,且目前处于停战(未开战)状态

3.(\(U\) \(x\) ) 第 \(x\) 次发生的战争结束了,它将永远的被载入史册,不复存在(保证这个消息不会告诉你多次)

\(\color{#0066ff}{输入格式}\)

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

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

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

\(\color{#0066ff}{输出格式}\)

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

\(\color{#0066ff}{输入样例}\)

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

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

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

\(\color{#0066ff}{输出样例}\)

Yes
No
No
No

Yes
No
No
Yes

Yes
Yes
Yes
Yes
No

\(\color{#0066ff}{数据范围与提示}\)

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

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

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

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

\(\color{#0066ff}{ 题解 }\)

一道裸的LCT维护连通性问题

开个pair记录一下每次发动战争的两点,这样就能O(1)找到某次战争

#include<bits/stdc++.h>
#define LL long long
LL in() {
    char ch; LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    return x * f;
}
const int maxn = 3e5 + 10;
struct LCT {
protected:
    struct node {
        node *fa, *ch[2];
        int rev;
        node(int rev = 0): rev(rev) { ch[0] = ch[1] = fa = NULL; }
        void trn() { std::swap(ch[0], ch[1]), rev ^= 1; }
        void dwn() {
            if(!rev) return;
            if(ch[0]) ch[0]->trn();
            if(ch[1]) ch[1]->trn();
            rev = 0;
        }
        bool isr() { return this == fa->ch[1]; }
        bool ntr() { return fa && (fa->ch[1] == this || fa->ch[0] == this); }
    }pool[maxn];
    void rot(node *x) {
        node *y = x->fa, *z = y->fa;
        bool k = x->isr(); node *w = x->ch[!k];
        if(y->ntr()) z->ch[y->isr()] = x;
        (x->ch[!k] = y)->ch[k] = w;
        (y->fa = x)->fa = z;
        if(w) w->fa = y;
    }
    void splay(node *o) {
        static node *st[maxn];
        int top;
        st[top = 1] = o;
        while(st[top]->ntr()) st[top + 1] = st[top]->fa, top++;
        while(top) st[top--]->dwn();
        while(o->ntr()) {
            if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa);
            rot(o);
        }
    }
    void access(node *x) {
        for(node *y = NULL; x; x = (y = x)->fa)
            splay(x), x->ch[1] = y;
    }
    void makeroot(node *o) { access(o), splay(o), o->trn(); }
    node *findroot(node *o) {
        access(o), splay(o);
        while(o->dwn(), o->ch[0]) o = o->ch[0];
        return o;
    }
public:
    void link(int l, int r) {
        node *x = pool + l, *y = pool + r;
        makeroot(x), x->fa = y;
    }
    void cut(int l, int r) {
        node *x = pool + l, *y = pool + r;
        makeroot(x), access(y), splay(y);
        if(y->ch[0] == x) y->ch[0] = x->fa = NULL;
    }
    bool query(int x, int y) { return findroot(pool + x) == findroot(pool + y); }
}s;
using std::pair;
pair<int, int> mp[maxn];
int num, n, m;
char getch() {
    char ch;
    while(!isalpha(ch = getchar()));
    return ch;
}
int main() {
    n = in(), m = in();
    int x;
    for(int i = 1; i < n; i++) s.link(in(), in());
    while(m --> 0) {
        char ch = getch();
        if(ch == 'Q') printf(s.query(in(), in())? "Yes\n" : "No\n");
        if(ch == 'C') mp[++num] = std::make_pair(in(), in()), s.cut(mp[num].first, mp[num].second);
        if(ch == 'U') x = in(), s.link(mp[x].first, mp[x].second);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/olinr/p/10392344.html

时间: 2024-10-31 21:38:38

P3950 部落冲突的相关文章

【luogu P3950 部落冲突】 题解

题目连接:https://www.luogu.org/problemnew/show/P3950 1.像我这种学数据结构学傻了的 2.边权化点权 所有点权初始化0 3.对于战争 将深度较深的-1,对于和平 将深度较深的+1 4.对于历史 用war记录 5.特别注意 在两个查询的LCA处判断是否为-1并且当前的整条路径上的点权也为-1时 同样是yes 代码: include include include include define lson left, mid, rt<<1 define r

计算部落冲突时长的工具

今天闲来无事,想找一个计算部落冲突建筑升级时间.发现没有得心应手的,就自己写了一个控制台输出的小程序. import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class T5 { public static void main(String[] args) { //获取当前系统毫秒 Date nowDate=new Date(System.currentTimeMill

部落冲突(Clash of Clans)12月更新官方资料:可掠夺资源比例调整的详细说明

部落冲突(Clash of Clans)12月更新官方资料:可掠夺资源比例调整的详细说明 们决定要调整战斗中可掠夺资源的比例了! 不要担心,冷静,冷静,再冷静,然后深呼吸,吸气,呼气-- 本次调整后的可掠夺资源计算办法实在是太复杂了,就这个题目写上一篇论文,发表在权威杂志也绰绰有余了,不过如果要长话短说的话就是: "玩家都将体会到更加容易积累与大本营级别相匹配的丰富资源,从而建造和升级昂贵的建筑,研究昂贵的兵种和法术.同时,通过调整不同大本营等级的可掠夺资源比例,你将会更容易找到大鱼."

Cogs 2856. [洛谷U14475]部落冲突

2856. [洛谷U14475]部落冲突 ★★★   输入文件:lct.in   输出文件:lct.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多可歌可泣的动人故事. 其中,在大大小小的部落之间,会有一些道路相连,这些道路是Travian世界里的重要枢纽,简单起见,你可以把这

部落冲突云手机多开改不同IP防检测挂机

现在很多手游工作室采用云手机多开这个技术挂机一个可以赚金的手游,云手机相当于一个虚拟手机的存在.云手机顾名思义是与云技术有关,但我不想讲的那么高深,大家可以百度一下阿里云,腾讯云等服务器了解一下,云手机就是云服务器下的虚拟框架手机.(安卓系统)可以叫它云手机,也可以叫它云平板.它不是手游模拟器,也不是真实手机.下面,小编我以<部落冲突>为例进行代练的操作示范 首先,安装部落冲突手游,以360版本为例,在360手游市场中搜索并安装<部落冲突>.这时,您可以启动并运行<部落冲突&

【Luogu P3950】部落冲突

Problem Description 给出一棵树. 你需要处理下面三件事,所有的事件都是按照时间顺序给出的. \(Q, u, v\) 代表询问 \(u, v\) 之间能否相互到达 \(C, u, v\) 代表 \(u, v\) 之间的边断开了 \(U, x\) 代表第 \(U\) 次 \(C\) 操作被还原 Input Format 第一行两个数 \(n\) 和 \(m\) , \(n\) 代表了一共有 \(n\) 个部落,\(m\) 代表了以上三种事件发生的总数 接下来的 \(n - 1\)

题解【部落冲突】

LCT学习ing……从FlshHu的大佬的博客中看到此题,于是便写了一下. 题目背景 在一个叫做Travian的世界里,生活着各个大大小小的部落.其中最为强大的是罗马.高卢和日耳曼.他们之间为了争夺资源和土地,进行了无数次的战斗.期间诞生了众多家喻户晓的英雄人物,也留下了许多可歌可泣的动人故事. 其中,在大大小小的部落之间,会有一些道路相连,这些道路是Travian世界里的重要枢纽,简单起见,你可以把这些部落与部落之间相连的道路看作一颗树,可见每条道路对于Travian世界的重要程度.有了这些道

[Luogu] 部落冲突--00

https://www.luogu.org/problemnew/show/P3950 思路简单,树剖不用动脑子 #include <bits/stdc++.h> using namespace std; const int N = 3e5 + 10; #define gc getchar() #define lson jd << 1 #define rson jd << 1 | 1 struct Node_1{ int v, nxt; }G[N << 1]

[luogu3950] 部落冲突 - Link Cut Tree

有了LCT这不就是思博题了吗 #include <bits/stdc++.h> using namespace std; const int N = 1000000; int n,m,t1,t2,t3; char op[5]; struct LinkCutTree { int top, q[N], ch[N][2], fa[N], rev[N]; inline void pushup(int x) { } inline void pushdown(int x) { if(!rev[x]) re