您的位置:首页 > 理论基础 > 计算机网络

snnu(1110) 传输网络 (并查集+路径压缩+离线操作 || 线段树)

2015-07-27 17:01 656 查看

1110: 传输网络

Time Limit: 3 Sec Memory Limit: 512 MB
Submit: 43 Solved: 18
[Submit][Status][Web Board] [Edit]

Description

Byteland国家的网络单向传输系统可以被看成是以首都Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的。现在他们开始在其他城市陆续建立了新的基站,命令“C x“代表在城市x建立了一个新的基站,不会在同一个城市建立多个基站;城市编号为1到n,其中城市1就是首都Bytetown。在建立基站的过程中他们还会询问某个城市的网络信号是从哪个城市传输过来的,命令”Q x“代表查询城市x的来源城市。

Input

输入有多组测试数据。每组数据的第一行包含两个正整数n和m(1 <= n,m <= 100,000),分别代表城市数和命令数。接下来n-1行,每行两个正整数u和v,代表一条从城市u到城市v的网络传输通道。之后的m行,每行一个命令”C x“或”Q x”。
所有输入的n和m的总和分别都不超过500,000,两组输入数据之间用一个空行隔开。

Output

对于每个查询命令,输出一个整数y,表示来源城市。每两组数据之间用一个空格隔开。

Sample Input

3 4
1 2
2 3
Q 3
C 2
Q 2
Q 3


Sample Output

1
2
2


HINT

Source

2015陕西省大学生程序设计竞赛

题目大意:给定一个关系树,有两种操作,一个是询问这个关系树的根节点,一个是将这个关系树分割。

可以使用并查集,由于关系树可能退化成一条链,每次查询时可能会查询整个链,考虑路径压缩,然而后面可能会有c操作,

对于这种问题,一大堆的询问操作和分割操作,相互交叉,类似于之前做过的一道题,求一段区间中相异数之和,全部读入查询操作,

进行编号,然后依次回答以结尾的查询操作,再根据编号回答,离线操作就是映射了一遍,这道题假设读入所有的c操作,建立一棵

终极树,貌似不能回答没有进行c操作之前的查询,不可能吗?

我们可以倒着做,回答最后一个c之后的查询,然后将这棵树还原到c之前的状态,再次回答,以此类推,将树的状态还原到初始状态,

对每一个状态我们都可以进行带有路压缩的查询了,降低了时间复杂度。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#define LL long long
using namespace std;
int answer=1;
//线段树
//区间染色
const int maxN = 110000;
struct node
{
int lt, rt, val, turn;
}tree[4*maxN];

//向下更新
void pushDown(int id)
{
if (tree[id].turn != 0)
{
tree[id<<1].turn  = max( tree[id << 1].val,tree[id].turn );
tree[id<<1].val = tree[id<<1].turn ;

tree[id<<1|1].turn = max( tree[id << 1 |1].val ,tree[id].turn );
tree[id << 1 |1].val= tree[id<<1 | 1].turn;

tree[id].turn = 0;
}
}

//向上更新
void pushUp(int id)
{
if (tree[id<<1].val == tree[id<<1|1].val)
tree[id].val = tree[id<<1].val;
else
tree[id].val = 0;
}

//建立线段树
void build(int lt, int rt, int id)
{
tree[id].lt = lt;
tree[id].rt = rt;
tree[id].val = 0;//每段的初值,根据题目要求
tree[id].turn = 0;
if (lt == rt)
{
tree[id].turn = 1;
tree[id].val  = 1;
return;
}
int mid = (lt+rt)>>1;
build(lt, mid, id<<1);
build(mid+1, rt, id<<1|1);
}

//更改每段的值,多用于染色
void change(int lt, int rt, int id, int col)
{
if (lt <= tree[id].lt && rt >= tree[id].rt)
{
tree[id].val = tree[id].turn = max( tree[id].turn ,col );
return;
}
pushDown(id);
int mid = (tree[id].lt+tree[id].rt)>>1;
if (lt <= mid)
change(lt, rt, id<<1, col);
if (rt > mid)
change(lt, rt, id<<1|1, col);
//pushUp(id);
}
/*
void query(int lt, int rt, int id)
{
if (lt > tree[id].rt || rt < tree[id].lt)
return;
if (tree[id].val != 0)
{
answer=tree[id].val;
return;
}
query(lt, rt, id<<1);
query(lt, rt, id<<1|1);
}*/
//查询单点的值
int query(int lt, int rt, int id)
{
if (lt <= tree[id].lt && rt >= tree[id].rt)
return tree[id].val;
pushDown(id);
int mid = (tree[id].lt + tree[id].rt) >> 1;
if (rt <= mid)
return query(lt, rt, id<<1);
if (lt > mid)
return query(lt, rt, id<<1|1);
}

struct NODE
{
int l,r;
}a[maxN];
typedef vector<int > INT;
vector<INT > Map(maxN);
int number;
void dfs(int fa)
{
for(int i=0;i<Map[fa].size();i++)
{
int son=Map[fa][i];
a[son].l= ++number;
dfs(son);
a[son].r=number;
}
}
void init()
{
for(int i=0;i<maxN;i++)
Map[i].clear();
}
int main()
{
//freopen("test.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m;
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=1;i<=n-1;i++)
{
int from,to;
scanf("%d%d",&from,&to);
Map[from].push_back(to);
}
number=1;
a[1].l=1;
dfs(1);
a[1].r=number;

build(a[1].l,a[1].r,1);
//  for(int i=1;i<=9;i++)
// printf("%d %d\n",a[i].l,a[i].r);
char str[5];   int id;
while(m--)
{
scanf("%s%d",str,&id);
//printf("%s\n",str);
if(str[0]=='Q')
{
// answer=1;
answer=query(a[id].l,a[id].l,1);
printf("%d\n", answer);
}
if(str[0]=='C')
{
change(a[id].l,a[id].r,1,id);
}
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: