数据结构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. sql查询 同一个字段下另一个字段个数

    select seriesid , count(reportid) from reportsystem group by seriesidhaving count(reportid) > 1

  2. 第一、二章——Python简介与Python基础

    前言:<Data Wrangling with Python>这本书主要是讲使用Pyhon来处理各种类型保存的数据的. 第一章:Python简介 1.版本选择 本书选择的Python版本是 ...

  3. 3dContactPointAnnotationTool开发日志(五)

      今天要做的第一件事就是把obj文件里不同的对象分割开来.   通过仔细观察发现obj文件中以"o "开头的行会跟着一个对象的名字.g代表对象所属组名,我这里只要用到对象名就行了 ...

  4. [TUTORIAL]How to setup SP_Flash_Tool_Linux (MTK/MediaTek Soc)

    转自:https://forum.xda-developers.com/general/rooting-roms/tutorial-how-to-setup-spflashtoollinux-t316 ...

  5. 第52天:offset家族、scroll家族和client家族的区别

    一.offset家族 1.offsetWidth offsetHeight offsetLeft offsetTop offsetParent共同组成了offset家族,用来获取元素尺寸. offse ...

  6. BZOJ4771 七彩树(dfs序+树上差分+主席树)

    考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...

  7. Apple - Hdu5160

    Problem Description We are going to distribute apples to n children. Every child has his/her desired ...

  8. 【题解】Atcoder ARC#90 F-Number of Digits

    Atcoder刷不动的每日一题... 首先注意到一个事实:随着 \(l, r\) 的增大,\(f(r) - f(l)\) 会越来越小.考虑暴力处理出小数据的情况,我们可以发现对于左端点 \(f(l) ...

  9. 【刷题】BZOJ 1717 [Usaco2006 Dec]Milk Patterns 产奶的模式

    Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". ...

  10. sd卡的访问

    一般再访问sd卡前都要获取sd卡的路径,以防止不同的厂商有不同的路径配置.Android提供了Environment类来获取系统当前sd卡路径. Log.d(TAG, Environment.getE ...