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小的值。
 

感觉怎么做都没什么思路.
学长说正解是分类讨论.
还真是分类讨论...
可以将所有数分为两种:小于等于 $k$ 的,大于 $k$ 的.
前一部分的数值是不变的,大于 $k$ 的数值都要变.
而我们还可以把大于 $k$ 的再分成大于 $2k$ 的和 $k<=a_{i}<=2k.$
而将 $a_{i}\in[k,2k]$ 的数减掉 $k$ 就相当于至少 / 2.
因为没有加法操作,所以每一个数至多会减少 $log(10^9)$ 次.
所以可以每一次用 $splay$ 将 $a_{i}\in[k,2k]$ 之间的数字提取出来,直接暴力减掉 $k$ 并重新插进平衡树.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100003;
namespace IO {
void setIO(string s) {
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
freopen(out.c_str(),"w",stdout);
}
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
int x=0;
char c=nc();
while(c<48) c=nc();
while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc();
return x;
}
};
int root;
int arr[maxn];
struct Splay {
#define lson ch[x][0]
#define rson ch[x][1]
stack<int>S;
int cnt,tp;
int ch[maxn][2],f[maxn],val[maxn],siz[maxn],tag[maxn],key[maxn];
void init() {
for(int i=1;i<maxn;++i) S.push(i);
}
int newnode() {
int x=S.top();S.pop();
return x;
}
void mark(int x,int d) {
val[x]-=d, tag[x]+=d;
}
int get(int x) {
return ch[f[x]][1]==x;
}
void pushup(int x) {
siz[x]=siz[lson]+siz[rson]+1;
}
void pushdown(int x) {
if(tag[x]) mark(lson,tag[x]),mark(rson,tag[x]),tag[x]=0;
}
void rotate(int x) {
int old=f[x],fold=f[old],which=get(x);
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=fold;
if(fold) ch[fold][ch[fold][1]==old]=x;
pushup(old),pushup(x);
}
void splay(int x,int &tar) {
int u=f[tar],fa;
for(;(fa=f[x])^u;rotate(x))
if(f[fa]^u)
rotate(get(fa)==get(x)?fa:x);
tar=x;
}
int pre(int v) {
int x=root,re=0;
while(x) {
pushdown(x);
if(val[x]<=v) re=x,x=rson;
else x=lson;
}
return re;
}
int nxt(int v) {
int x=root,re=0;
while(x) {
pushdown(x);
if(val[x]>=v) re=x,x=lson;
else x=rson;
}
return re;
}
void build(int &x,int ff,int l,int r) {
x=newnode();
int mid=(l+r)>>1;
f[x]=ff,val[x]=arr[mid],siz[x]=1;
if(l<mid) build(lson,x,l,mid-1);
if(r>mid) build(rson,x,mid+1,r);
pushup(x);
}
int insert(int &x,int ff,int k) {
if(!x) {
x=newnode();
f[x]=ff,val[x]=k,siz[x]=1;
pushup(x);
return x;
}
pushdown(x);
int a=insert(ch[x][k>val[x]],x,k);
pushup(x);
return a;
}
void dfs(int x) {
if(!x) return;
pushdown(x);
key[++tp]=val[x];
if(lson) dfs(lson);
if(rson) dfs(rson);
S.push(x);
ch[x][0]=ch[x][1]=f[x]=val[x]=siz[x]=tag[x]=0;
}
int kth(int k) {
int x=root;
while(1) {
pushdown(x);
if(k>siz[lson]) {
k-=(siz[lson]+1);
if(k==0) return val[x];
else x=rson;
}
else x=lson;
}
}
void solve(int k) {
int pr=pre(k),nx=nxt(k<<1);
if(!pr) mark(root,k);
else if(!nx) {
splay(pr,root);
int a=ch[root][1];
ch[root][1]=f[ch[root][1]]=0;
pushup(root);
tp=0;
dfs(a);
for(int i=1;i<=tp;++i) {
int cc=insert(root,0,key[i]-k);
if(i%6==0) splay(cc,root);
}
}
else {
splay(pr,root),splay(nx,ch[root][1]);
int a=ch[ch[root][1]][0];
ch[ch[root][1]][0]=0, pushup(ch[root][1]);
tp=0, dfs(a);
mark(ch[root][1], k);
for(int i=1;i<=tp;++i) {
int cc=insert(root,0,key[i]-k);
if(i%6==0) splay(cc,root);
}
}
}
#undef lson
#undef rson
}tr;
int main() {
using namespace IO;
// setIO("input");
tr.init();
int n,m;
n=rd(),m=rd();
for(int i=1;i<=n;++i) arr[i]=rd();
sort(arr+1,arr+1+n);
tr.build(root,0,1,n);
for(int cas=1;cas<=m;++cas) {
int op,k;
op=rd(),k=rd();
if(op==1) printf("%d\n",tr.kth(k));
else tr.solve(k);
}
return 0;
}

  

BZOJ 4923: [Lydsy1706月赛]K小值查询 Splay + 思维的更多相关文章

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

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

  2. BZOJ4923:[Lydsy1706月赛]K小值查询(Splay)

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

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

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

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

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

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

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

  6. [bzoj4923]K小值查询

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

  7. BZOJ4923 K小值查询(splay)

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

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

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

  9. bzoj 3065: 带插入区间K小值 替罪羊树 && AC300

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1062  Solved: 253[Submit][Status] Des ...

随机推荐

  1. 编译中出现的undefined reference to XXX

    主要是在链接时发现找不到某个函数的实现文件.可以查找是否在makefile里没有增加待编译的.c文件,或者静态库没有引用

  2. 【Qt开发】Qt中图像的显示与基本操作

    Qt可显示基本的图像类型,利用QImage.QPxmap类可以实现图像的显示,并且利用类中的方法可以实现图像的基本操作(缩放.旋转). 1. Qt可显示的图像类型 参考Qt的帮助文档,可支持的类型,即 ...

  3. [Git] 021 来一颗“恶魔果实”?

    0. 前言 需要新的功能时,一般会新建一条 "feature" 分支(尴尬的是,我第一眼看时,看成了 "future") 在 "feature&quo ...

  4. 《剑指offer》面试题25 二叉树中和为某一值的路径 Java版

    (判断是否有从根到叶子节点的路径,其和为给定值.记录这些路径.) 我的方法:这道题我是按照回溯的思路去做的,我们需要一个数据结构来保存和删除当前递归函数中添加的值.这里要打印一条路径,我们可以选择Li ...

  5. KMP字符串匹配 模板 洛谷 P3375

    KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...

  6. NOIP赛前集训备忘录(含每日总结)(日更?。。。)

    NOIP赛前集训备忘录(含每日考试总结) 标签: 有用的东西~(≧▽≦)/~啦啦啦 阅读体验:https://zybuluo.com/Junlier/note/1279194 考试每日总结(这个东西是 ...

  7. 关于微信H5页面开发中音乐不自动播放的解决方法

    我想应该有很多人在做H5场景应用.H5微刊.H5微杂志的时候加入背景音乐吧(客户需求),相信很多人一定碰过不能自动播放的时候,即使是相同的iPhone 5s也有不播放的时候,很蛋疼吧!? 之前我的解决 ...

  8. PHP 经典有趣的算法

    原文:https://blog.csdn.net/a519395243/article/details/77942913 1.一群猴子排成一圈,按1,2,…,n依次编号.然后从第1只开始数,数到第m只 ...

  9. CSP2019

    $CSP\space S$ 格雷码 $solution:$ 直接模拟即可. 时间复杂度 $O(n)$ . #include<iostream> #include<cstring> ...

  10. spring boot 枚举使用的坑2

    上一篇说到在枚举当在controller的方法做参数时的坑,解决方法是配置了一个converter,后来想想,如果不闲每次都加一个注解麻烦的话,可以在参数前面加一个注解,添加一个解析器应该也可以解决这 ...