题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4923
解法题解里说的挺清楚的,好吧,我就是找个地方存一哈代码...
辣鸡卡常题,跑了16s竟然判过了....实在是优化不动了
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100010;
const int INF=2e9+5;
int a[MAXN];
int n,q;
namespace Splay_Tree
{
#define Key_value ch[ch[root][1]][0]
int pre[MAXN],ch[MAXN][2],key[MAXN],size[MAXN],sub[MAXN],tmp[MAXN];
int root,tot1,cnt;
inline void NewNode(int &r,int father,int k)
{
r=++tot1;
pre[r]=father;
ch[r][0]=ch[r][1]=0;
key[r]=k;
size[r]=1;
sub[r]=0;
}
inline void push_up(int r)
{
int lson=ch[r][0],rson=ch[r][1];
size[r]=size[lson]+size[rson]+1;
}
inline void up_sub(int r,int k)
{
if(!r)
return ;
if(key[r]!=-1&&key[r]!=INF)
key[r]-=k;
sub[r]+=k;
}
inline void push_down(int r)
{
if(sub[r])
{
up_sub(ch[r][0],sub[r]);
up_sub(ch[r][1],sub[r]);
sub[r]=0;
}
}
inline void Build(int &x,int l,int r,int father)
{
if(l>r)
return;
int mid=(l+r)/2;
NewNode(x,father,a[mid]);
Build(ch[x][0],l,mid-1,x);
Build(ch[x][1],mid+1,r,x);
push_up(x);
}
inline void Init()
{
root=tot1=0;
ch[root][0]=ch[root][1]=size[root]=pre[root]=0;
key[root]=0;
sub[root]=0;
NewNode(root,0,-1);
NewNode(ch[root][1],root,INF);
Build(Key_value,1,n,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
//旋转,0为左旋,1为右旋
inline void Rotate(int x,int kind)
{
int y=pre[x];
push_down(y);
push_down(x);
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if(pre[y])
ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
push_up(y);
}
//Splay调整,将r结点调整到goal下面
inline void Splay(int r,int goal)
{
push_down(r);
while(pre[r]!=goal)
{
if(pre[pre[r]]==goal)
{
push_down(pre[r]);
push_down(r);
Rotate(r,ch[pre[r]][0]==r);
}
else
{
push_down(pre[pre[r]]);
push_down(pre[r]);
push_down(r);
int y=pre[r];
int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==r)
{
Rotate(r,!kind);
Rotate(r,kind);
}
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
push_up(r);
if(goal==0)
root=r;
}
//获得第K个位置数
inline int Get_kth(int r,int k)
{
push_down(r);
int t=size[ch[r][0]]+1;
if(t==k)
return r;
if(t>k)
return Get_kth(ch[r][0],k);
else
return Get_kth(ch[r][1],k-t);
}
inline int Get_mx(int r)
{
push_down(r);
if(ch[r][1])
return Get_mx(ch[r][1]);
return r;
}
inline int Get_mi(int r)
{
push_down(r);
if(ch[r][0])
return Get_mx(ch[r][0]);
return r;
}
inline int Get_ri(int r,int k)
{
int ret=-1;
while(1)
{
push_down(r);
if(key[r]>k)
{
ret=r;
if(ch[r][0])
r=ch[r][0];
else
return ret;
}
else
{
if(ch[r][1])
r=ch[r][1];
else
return ret;
}
}
}
inline int Get_lf(int r,int k)
{
int ret=-1;
while(1)
{
push_down(r);
if(key[r]<=k)
{
ret=r;
if(ch[r][1])
r=ch[r][1];
else
return ret;
}
else
{
if(ch[r][0])
r=ch[r][0];
else
return ret;
}
}
}
inline void InOrder(int r)
{
if(!r)
return;
push_down(r);
InOrder(ch[r][0]);
tmp[cnt++]=r;
InOrder(ch[r][1]);
}
inline int Get_next(int r)
{
push_down(r);
if(ch[r][1]==0)
return -1;
r=ch[r][1];
push_down(r);
while(ch[r][0])
{
r=ch[r][0];
push_down(r);
}
return r;
}
void Insert(int r,int now)
{
push_down(r);
if(key[tmp[now]]<key[r])
{
if(ch[r][0])
{
Insert(ch[r][0],now);
}
else
{
pre[tmp[now]]=r;
ch[r][0]=tmp[now];
ch[tmp[now]][0]=ch[tmp[now]][1]=0;
size[tmp[now]]=1;
sub[tmp[now]]=0;
}
push_up(r);
}
if(key[tmp[now]]>=key[r])
{
if(ch[r][1])
{
Insert(ch[r][1],now);
}
else
{
pre[tmp[now]]=r;
ch[r][1]=tmp[now];
ch[tmp[now]][0]=ch[tmp[now]][1]=0;
size[tmp[now]]=1;
sub[tmp[now]]=0;
}
push_up(r);
}
}
void change(int k)
{
int l=Get_lf(root,k);
Splay(l,0);
int r=Get_ri(root,k+k);
Splay(r,root);
if(key[ch[root][1]]!=INF)
{
key[ch[root][1]]-=k;
}
sub[ch[root][1]]+=k;
push_down(ch[root][1]);
if(Key_value==0)
return ;
int sv=Key_value;
cnt=0;
pre[sv]=0;
Key_value=0;
InOrder(sv);
int now=0;
while(now<cnt)
Insert(root,now++);
}
}
using namespace Splay_Tree;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x)
{
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
int op,k;
int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
rea(n);rea(q);
for(int i=1;i<=n;i++)
{
rea(a[i]);
}
sort(a+1,a+1+n);
Init();
Splay(1,0);
while(q--)
{
rea(op);
rea(k);
if(op==1)
{
printf("%d\n",key[Get_kth(root,k+1)]);
}
else
{
change(k);
}
}
return 0;
}