Description

维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作:
1 k,将序列a从小到大排序,输出a_k的值。
2 k,将所有严格大于k的数a_i减去k。

Input

第一行包含两个正整数n,m(1<=n,m<=100000),分别表示序列的长度和操作的个数。
第二行包含n个正整数a_1,a_2,...,a_n(1<=a_i<=10^9),分别表示序列中的每个元素。
接下来m行,每行两个正整数op(1<=op<=2),k,若op=1,则1<=k<=n;若op=2,则1<=k<=10^9;依次描述每个操作。

Output

输出若干行,对于每个询问输出一行一个整数,即第k小的值。

Sample Input

4 5
1 5 6 12
2 5
1 1
1 2
1 3
1 4

Sample Output

1
1
5
7

Solution

把数排个序然后建$Splay$,每次修改对值域为$[1,k]$中的不管,$[k+1,k\times 2]$中的拆出来改完了再暴力插回去,对于$[k\times 2+1,MAX]$中打标记。我也不知道为什么复杂度是对的。

以后别有事没事把标记下传到$0$点,修改着修改着$0$下标的值就不知道被修改成什么鬼畜的数了。

Code

 #include<iostream>
#include<cstdio>
#include<algorithm>
#define N (100009)
using namespace std; int n,m,opt,k,a[N];
int Root,Father[N],Son[N][];
int Val[N],Size[N],Max[N],Add[N]; int Get(int x) {return Son[Father[x]][]==x;} void Pushup(int x)
{
Size[x]=Size[Son[x][]]+Size[Son[x][]]+;
Max[x]=max(Val[x],max(Max[Son[x][]],Max[Son[x][]]));
} int Build(int fa,int l,int r)
{
if (l>r) return ;
int mid=(l+r)>>;
Father[mid]=fa; Val[mid]=a[mid];
Son[mid][]=Build(mid,l,mid-);
Son[mid][]=Build(mid,mid+,r);
Pushup(mid); return mid;
} void Rotate(int x)
{
int wh=Get(x);
int fa=Father[x],fafa=Father[fa];
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Father[fa]=x; Son[fa][wh]=Son[x][wh^];
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Father[x]=fafa; Son[x][wh^]=fa;
Pushup(fa); Pushup(x);
} void Pushdown(int x)
{
if (Add[x]!=)
{
if (Son[x][])
{
Val[Son[x][]]+=Add[x];
Add[Son[x][]]+=Add[x];
Max[Son[x][]]+=Add[x];
}
if (Son[x][])
{
Val[Son[x][]]+=Add[x];
Add[Son[x][]]+=Add[x];
Max[Son[x][]]+=Add[x];
}
Add[x]=;
}
} void Push(int x)
{
if (Father[x]) Push(Father[x]);
Pushdown(x);
} void Splay(int x,int tar)
{
Push(x);
for (int fa; (fa=Father[x])!=tar; Rotate(x))
if (Father[fa]!=tar)
Rotate(Get(fa)==Get(x)?fa:x);
if (!tar) Root=x;
} int Findkth(int x)
{
int now=Root;
while ()
{
Pushdown(now);
if (Size[Son[now][]]>=x) now=Son[now][];
else
{
x-=Size[Son[now][]];
if (x==) {Splay(now,); return Val[now];}
x--; now=Son[now][];
}
}
} int Find(int x)
{
int now=Root,ans=;
while ()
{
Pushdown(now);
if (Max[Son[now][]]>x) now=Son[now][];
else
{
if (Val[now]>x) {Splay(now,); return now;}
now=Son[now][];
}
}
} int Pre(int x)
{
Splay(x,);
x=Son[x][];
while (Son[x][]) x=Son[x][];
return x;
} void Insert(int x)
{
int now=Root,fa=;
while ()
{
Pushdown(now);
if (!now)
{
Father[x]=fa;
Son[fa][Val[fa]<Val[x]]=x;
Max[x]=Val[x]; Size[x]=;
Splay(x,); return;
}
fa=now, now=Son[now][Val[now]<Val[x]];
}
} void DFS(int x,int k)
{
if (!x) return;
Pushdown(x);
DFS(Son[x][],k); DFS(Son[x][],k);
Father[x]=Son[x][]=Son[x][]=Size[x]=Max[x]=;
Val[x]-=k; Insert(x);
} void Update(int k)
{
int x=Pre(Find(k)),y=Find(*k);
Splay(x,); Splay(y,x);
int s=Son[y][]; Son[y][]=Father[Son[y][]]=;
DFS(s,k);
Splay(y,);
x=Pre(Find(*k)),y=n+;
Splay(x,); Splay(y,x);
if (!Son[y][]) return;
Add[Son[y][]]-=k; Val[Son[y][]]-=k; Max[Son[y][]]-=k;
} int main()
{
scanf("%d%d",&n,&m);
for (int i=; i<=n+; ++i)
scanf("%d",&a[i]);
a[]=-2e9; a[n+]=2e9; Max[]=-2e9;
sort(a+,a+n+);
Root=Build(,,n+);
for (int i=; i<=m; ++i)
{
scanf("%d%d",&opt,&k);
if (opt==) printf("%d\n",Findkth(k+));
else Update(k);
}
}

BZOJ4923:[Lydsy1706月赛]K小值查询(Splay)的更多相关文章

  1. BZOJ 4923: [Lydsy1706月赛]K小值查询 Splay + 思维

    Description 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. In ...

  2. BZOJ4923 [Lydsy1706月赛]K小值查询

    题意 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. \(n \leq 10 ...

  3. [BZ4923][Lydsy1706月赛]K小值查询

    K小值查询 题面 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. Input ...

  4. 4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap

    国际惯例的题面:这种维护排序序列,严格大于的进行操作的题都很套路......我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好.显然第一个区间的不会变化,第二个区间的会被平移进第一个区 ...

  5. [BZOJ 4923][Lydsy1706月赛]K小值查询

    传送门 势能分析平衡树,splay或treap都可以 放个指针版的就跑 #include <bits/stdc++.h> using namespace std; #define rep( ...

  6. BZOJ4923 K小值查询(splay)

    容易想到建一棵平衡树,修改时打上标记即可.但是修改会导致平衡树结构被破坏.注意到实际上只有[k+1,2k)这一部分数在平衡树中的位置会被改变,所以对这一部分暴力修改,因为每次都会使其至少减小一半,复杂 ...

  7. [bzoj4923]K小值查询

    来自FallDream的博客,未经允许,请勿转载,谢谢. 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有 ...

  8. 【BZOJ】3065: 带插入区间K小值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3065 题意:带插入.修改的区间k小值在线查询.(原序列n<=35000, 询问<=175 ...

  9. 「BZOJ3065」带插入区间第K小值 替罪羊树×线段树

    题目描述 从前有\(n\)只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力\(a_i\).跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间\(k\)小值.他 ...

随机推荐

  1. WPF备忘录(5)怎样修改模板中的控件

    首先,想问大家一个问题,你们如果要给一个Button添加背景图片会怎么做?(呵呵,这个问题又点小白哈) 是这样吗? <Button Height="57" Horizonta ...

  2. redis缓存工具类,提供序列化接口

    1.序列化工具类 package com.qicheshetuan.backend.util; import java.io.ByteArrayInputStream; import java.io. ...

  3. 实现泛型数组的冒泡排序算法 C#

    public static class BubbleSortTool { public static void BubbleSort<T>(this T[] array, Ascendin ...

  4. mongdb基本操作和更新操作

    1.创建数据库 use hqj 不会真正的创建db,只有insert之后才会创建2.查看数据库show dbs3.插入文档db.hqj.insert({name:'111'})4.查看所有的文档sho ...

  5. Hamming Problem(hdu3199)

    Hamming Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. ssm中逆向工程与分页的应用

    昨天对springboot中的mybatis逆向工程与分页应用进行了整理,今天对ssm项目中的逆向工程与分页进行整理. 项目运行环境:eclipse+jdk1.8+maven+tomcat 一.搭建s ...

  7. [转载] Spring框架——AOP前置、后置、环绕、异常通知

    通知类型: 步骤: 1. 定义接口 2. 编写对象(被代理对象=目标对象) 3. 编写通知(前置通知目标方法调用前调用) 4. 在beans.xml文件配置 4.1 配置 被代理对象=目标对象 4.2 ...

  8. js 日文全半角转换

    客户的需求是,输入半角字符或日语假名,筛选出来的结果显示包含该字符的半角形式和全角形式的所有结果,输入全角也是同样的结果.这里就需要将输入的字符全部转为半角和全角,再去匹配结果. 在网上搜了一圈之后, ...

  9. HDU1402(fft)

    A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  10. POJ1741(SummerTrainingDay08-G 树的点分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 23380   Accepted: 7748 Description ...