数据结构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. 20172333 2017-2018-2 《Java程序设计》第7周学习总结

    20172333 2017-2018-2 <Java程序设计>第7周学习总结 教材学习内容 1.继承是创建新类的快捷方式之一,继承可以使用父类的所有方法及对象. 2.继承具有单向性,父类不 ...

  2. Python 服务器端表单验证插件

    Python格式验证库 Cerberus 作者 MrStranger 关注 2016.08.02 14:44 字数 2140 阅读 79评论 0喜欢 1 Cerberus是一个验证Python对象.M ...

  3. 《学习OpenCV》课后习题解答1

    题目:(P104) 下面这个练习是帮助掌握矩阵类型.创造一个三通道二维矩阵,字节类型,大小为100*100,并设置所有数值为0. a.在矩阵中使用cvCircle( CvArr* img, CvPoi ...

  4. YaoLingJump开发者日志(八)V1.1版本完成

    跳跃吧瑶玲下载连接 官网下载(网站服务器不支持10M以上的文件上传-_-||) 百度网盘下载 介绍   忙里偷闲,把之前的工作整理了一下完成V1.1版本,下面是更新! (1)去掉了积分榜. (2)增加 ...

  5. Jenkins系列-Jenkins用户权限和角色配置

    由于jenkins默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,这边将使用Role Strategy Plugin,介绍页面:https://wiki.jenki ...

  6. 抽象类 C#

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

  7. hibernate.cfg.xml的详细解释

    <!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表明XML文件的编码方式-->                    < ...

  8. js 复制到剪贴板 兼容还得自己想办法

    clipboard.js https://github.com/zenorocha/clipboard.js/ 主要问题还是ie8, 可以使用ie 特有的方法 if (window.clipboard ...

  9. Go语言【第五篇】:Go条件语句

    Go语言条件 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为true来决定是否执行指定语句,并在条件为false的情况再执行另外的语句.下图展示了程序语言中条件语句的结构: Go语言提 ...

  10. Springboot2.x+shiro+redis(Lettuce)整合填坑

    主要记录关键和有坑的地方 前提: 1.SpringBoot+shiro已经集成完毕,如果没有集成,先查阅之前的Springboot2.0 集成shiro权限管理 2.redis已经安装完成 3.red ...