数据结构C

Time Limit: 20 Sec  Memory Limit: 512 MB

Description

  

Input

  

Output

  

Sample Input

  

Sample Output

  

HINT

  

Solution

  首先,D操作为删除操作显然不可做,又发现这道题可以离线处理,那么我们考虑倒着来,维护加入操作。

  那么这时候,D操作就变为了合并操作,那么这时候我们只需要维护一个:可以支持单点修改查询第 k 大信息可合并的数据结构即可。

  显然构建若干棵权值线段树即可!对于每个联通块维护一棵线段树,用并查集判断两点是否在一个块内。

  这时候,D操作显然判断一下两点是否在一个联通块内,不在则合并两棵线段树;Q操作就是查询第 k 大,在树上二分即可;C操作就是原来值个数-1新加入值个数+1

  就简单地解决了这题啦!(本质上就是BZOJ1926弱化 + BZOJ1015 QWQ)

Code

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std; const int ONE = ;
const int INF = 2e6;
const int Base = 1e6; int n, m;
int opt, x, val;
int Val[];
char s[]; int Ans[], ans_num = ; int fat[]; int Num = , del[];
struct power {int opt, x, val;} oper[ONE];
struct point {int x, y;} a[];
int total = ;
struct seg
{
int root;
int left, right;
int val;
}Node[ONE * ]; int get()
{
int res=,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} int Find(int x)
{
if(fat[x] == x) return x;
return fat[x] = Find(fat[x]);
} void Un(int x, int y)
{
int f1 = Find(x), f2 = Find(y);
if(f1 != f2) fat[f1] = f2;
} void Update(int &i, int l, int r, int Val, int opt) //pos = Val , + opt
{
if(!i) i = ++total; Node[i].val = Node[i].val + opt; if(l == r) return;
int mid = l + r >> ; if(Val <= mid) Update(Node[i].left, l, mid, Val, opt);
else Update(Node[i].right, mid + , r, Val, opt); } int Merge(int y, int x) //y merge to x
{
if(x == || y == ) return x + y; Node[x].val += Node[y].val;
Node[x].left = Merge(Node[x].left, Node[y].left);
Node[x].right = Merge(Node[x].right, Node[y].right); return x;
} int Query(int i, int l, int r, int k) //k da
{
if(l == r) return l;
int mid = l + r >> , Val = Node[ Node[i].right ].val; if(k > Val)
return Query(Node[i].left, l, mid, k - Val);
else
return Query(Node[i].right, mid + , r, k);
} void Deal_first()
{
for(int i = ; i <= n; i++)
fat[i] = i, Node[i].root = ++total;
for(int i = ; i <= m; i++)
if(del[i] != ) Un(a[i].x, a[i].y);
for(int i = ; i <= n; i++)
Update(Node[Find(i)].root, , INF, Val[i], );
} void Deal_add(int x, int y)
{
x = Find(x), y = Find(y);
if(x == y) return;
Merge(Node[x].root, Node[y].root);
fat[x] = y;
} void Deal_query(int root, int k)
{
root = Find(root);
if(Node[root].val < k) {Ans[++ans_num] = + Base; return;}
Ans[++ans_num] = Query(Node[root].root, , INF, k);
} void Deal_change(int x, int y) //x is point, y is need val
{
int root = Find(x);
Update(Node[root].root, , INF, Val[x], -);
Update(Node[root].root, , INF, y, );
Val[x] = y;
} int main()
{
n = get(); m = get(); for(int i = ; i <= n; i++) Val[i] = get() + Base;
for(int i = ; i <= m; i++)
a[i].x = get(), a[i].y = get();
for(;;)
{
scanf("%s", s);
if(s[] == 'E') break;
if(s[] == 'D')
x = get(), del[x] = , oper[++Num] = (power){, x, };
if(s[] == 'Q')
x = get(), val = get(), oper[++Num] = (power){, x, val};
if(s[] == 'C')
x = get(), val = get(), oper[++Num] = (power){, x, Val[x]}, Val[x] = val + Base;
} Deal_first();
for(int i = Num; i >= ; i--)
{
if(oper[i].opt == ) Deal_add(a[ oper[i].x ].x, a[ oper[i].x ].y);
if(oper[i].opt == ) Deal_query(oper[i].x, oper[i].val);
if(oper[i].opt == ) Deal_change(oper[i].x, oper[i].val);
} for(int i = ans_num; i >= ; i--)
printf("%d\n", Ans[i] - Base);
}
  • [提交][状态][讨论]

【Foreign】数据结构C [线段树]的更多相关文章

  1. 数据结构-PHP 线段树的实现

    转: 数据结构-PHP 线段树的实现 1.线段树介绍 线段树是基于区间的统计查询,线段树是一种 二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.使用线段树可以快速的查 ...

  2. 【数据结构】线段树(Segment Tree)

    假设我们现在拿到了一个非常大的数组,对于这个数组里面的数字要反复不断地做两个操作. 1.(query)随机在这个数组中选一个区间,求出这个区间所有数的和. 2.(update)不断地随机修改这个数组中 ...

  3. 数据结构1 线段树查询一个区间的O(log N) 复杂度的证明

    线段树属于二叉树, 其核心特征就是支持区间加法,这样就可以把任意待查询的区间$[L, R]$分解到线段树的节点上去,再把这些节点的信息合并起来从而得到区间$[L,R]$的信息. 下面证明在线段树上查询 ...

  4. 数据结构(线段树):Educational Codeforces Round 6 620E. New Year Tree

    E. New Year Tree time limit per test 3 seconds memory limit per test 256 megabytes input standard in ...

  5. 数据结构(线段树):BZOJ 1568 [JSOI2008]Blue Mary开公司

    1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 602  Solved: 214[Submit ...

  6. 牛客练习赛28 B数据结构(线段树)

    链接:https://www.nowcoder.com/acm/contest/200/B来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...

  7. 2018.10.12 NOIP模拟 数据结构(线段树)

    传送门 sb线段树题居然还卡常. 修改操作直接更新区间最小值和区间标记下传即可. 询问加起来最多5e65e65e6个数. 因此直接询问5e65e65e6次最小值就行了. 代码

  8. 【uoj#228】基础数据结构练习题 线段树+均摊分析

    题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有三种:区间加.区间开根.区间求和. $n,m,a_i\le 100000$ . 题解 线段树+均摊分析 对于原来的两个数 $a$ ...

  9. 【Foreign】Weed [线段树]

    Weed Time Limit: 20 Sec  Memory Limit: 512 MB Description 从前有个栈,一开始是空的. 你写下了 m 个操作,每个操作形如 k v : 若 k ...

随机推荐

  1. 针对“来用”团队项目之NABC分析

    本项目特点之一:扩展性强 NABC分析: N(need):我们这个开发的这个软件主要是集娱乐软件和实用工具于一身的大容器,这里面有很多应用程序,针对不同用户需要,至少有一款应用程序能够满足用户的需要, ...

  2. Java之I/O流(第1部分)

    Java 中的I/O流: 1. 输入/输出流原理: 如下图所示:在 java 程序中,对于数据的输入/输出操作以“流”(Stream)的方式进行:J2SDK 提供了各种各样的“流”类,用来获取不同种类 ...

  3. Alpha 冲刺3

    队名:日不落战队 安琪(队长) 今天完成的任务 组织第三次站立式会议. 完成了个人信息前端界面. 明天的计划 草稿箱前端界面. 个人信息扩展界面框架. 还剩下的任务 回收站前端界面. 信息修改前端界面 ...

  4. s3c2440调试nandflash裸机程序遇到的问题

    图挂了可以去 https://github.com/tanghammer/mini2440_peripherals/blob/master/nand/debug_nand.md 按照前面sdram的代 ...

  5. PAT 甲级 1032 Sharing

    https://pintia.cn/problem-sets/994805342720868352/problems/994805460652113920 To store English words ...

  6. xpath教程二 ---- 通过ID和Class检索

    必备知识点 在html中,id是唯一的 在html中,class是可以多处引用的 工具 Python3版本 lxml库[优点是解析快] HTML代码块[从网络中获取或者自己杜撰一个] requests ...

  7. 图像检测算法Halcon 10的使用

    安装完成HALCON之后,在VS项目中添加动态链接库配置项目,并修改此项目属性的包含目录.库目录和链接器.

  8. MD5加密的使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. 第29天:js-数组添加删除、数组和字符串相互转换

    一.添加数组var arr=[1,3,5];arr.push(7,9);//添加7和9到数组arr后面,得到[1,3,5,7,9]1.push();可向数组末尾添加一个或多个元素,并返回新的长度.2. ...

  10. xsy1436-括号游戏

    题目 递归定义括号序列: 空串是括号序列 (A)是一个括号序列,其中A为括号序列 AB是一个括号序列,其中A,B均为括号序列 定义严格括号序列为形如(A)的括号序列,其中A为括号序列. 给出一个长度为 ...