【Foreign】数据结构C [线段树]
数据结构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 [线段树]的更多相关文章
- 数据结构-PHP 线段树的实现
转: 数据结构-PHP 线段树的实现 1.线段树介绍 线段树是基于区间的统计查询,线段树是一种 二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.使用线段树可以快速的查 ...
- 【数据结构】线段树(Segment Tree)
假设我们现在拿到了一个非常大的数组,对于这个数组里面的数字要反复不断地做两个操作. 1.(query)随机在这个数组中选一个区间,求出这个区间所有数的和. 2.(update)不断地随机修改这个数组中 ...
- 数据结构1 线段树查询一个区间的O(log N) 复杂度的证明
线段树属于二叉树, 其核心特征就是支持区间加法,这样就可以把任意待查询的区间$[L, R]$分解到线段树的节点上去,再把这些节点的信息合并起来从而得到区间$[L,R]$的信息. 下面证明在线段树上查询 ...
- 数据结构(线段树):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 ...
- 数据结构(线段树):BZOJ 1568 [JSOI2008]Blue Mary开公司
1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 602 Solved: 214[Submit ...
- 牛客练习赛28 B数据结构(线段树)
链接:https://www.nowcoder.com/acm/contest/200/B来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- 2018.10.12 NOIP模拟 数据结构(线段树)
传送门 sb线段树题居然还卡常. 修改操作直接更新区间最小值和区间标记下传即可. 询问加起来最多5e65e65e6个数. 因此直接询问5e65e65e6次最小值就行了. 代码
- 【uoj#228】基础数据结构练习题 线段树+均摊分析
题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有三种:区间加.区间开根.区间求和. $n,m,a_i\le 100000$ . 题解 线段树+均摊分析 对于原来的两个数 $a$ ...
- 【Foreign】Weed [线段树]
Weed Time Limit: 20 Sec Memory Limit: 512 MB Description 从前有个栈,一开始是空的. 你写下了 m 个操作,每个操作形如 k v : 若 k ...
随机推荐
- c#调用c++dll(c++界面在c#显示)____制作dll
1.c++dll含界面,以摄像头dll为例: 1.直接在c++SDK上调试运行成功,生成dll. 2.留一个调用接口(格式如下,写在cpp文件中,即函数体): extern "C" ...
- 常用排序算法--java版
package com.whw.sortPractice; import java.util.Arrays; public class Sort { /** * 遍历一个数组 * @param sor ...
- TCP系列37—Keep Alive—1、TCP存活检测
一.TCP存活(keepalive)检测的背景 对于TCP设计来说,如果一个客户端和服务器端建立连接后,不在进行数据传输,那么这个连接将会一直存在下去,理论上即使中间的路由器崩溃重启.或者中间的网络线 ...
- PagedDataSource数据绑定控件和AspNetPager分页控件结合使用列表分页
1.引用AspNetPager.dll. 2.放置Repeater数据绑定控件. <asp:Repeater ID="Repeater1" runat="serve ...
- Tomcat启动报错ERROR:transport error 202:bind failed:Address already
昨天在服务器上拷贝了一个tomcat项目,修改了server.xml之后启动居然报错ERROR:transport error 202:bind failed:Address already,应该是远 ...
- 百度地图常用2.0使用以及调用js
/** * 生成一条路线 * @param {Object} baiduMap 百度地图的 map对象 * @param {Object} lineColor 线路颜色 * @param {Objec ...
- React Components Template
React Components Template "use strict"; /** * * @author xgqfrms * @license MIT * @copyrigh ...
- 第51天:封装可视区域大小函数client
一.client 可视区域 offsetWidth: width + padding + border (披着羊皮的狼) clientWidth: width + ...
- BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)
容易想到的做法是建出AC自动机,高斯消元.然而自动机上节点数量是nm的. 注意到我们要求的变量只有n个,考虑将其他不用求的节点合并为一个变量.这个变量即表示随机生成一个串,其不包含任何一个模板串的概率 ...
- 【刷题】洛谷 P3809 【模板】后缀排序
题目背景 这是一道模板题. 题目描述 读入一个长度为 \(n\) 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置. ...