**************************************************************
Problem: 1503
User: 704035233
Language: C++
Result: Accepted
Time:912 ms
Memory:6348 kb
****************************************************************/
/*happywu
* 2014.8.13
* bzoj 1503 splay
*/
#include<cstdio>
#include<iostream>
#define Rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
typedef long long LL;
const int MAX_N = 200010;
struct Node
{
int key,num,Size,fa;
int son[2];
}Tree[MAX_N];
int root=0,tot=0,n;
inline void Push_Down(int x)
{
//此题无Push_Down操作
}
inline void Updata(int x)
{
Tree[x].Size = Tree[Tree[x].son[0]].Size + Tree[Tree[x].son[1]].Size + Tree[x].num;
}
inline void Rotate(int x,int c){
int y = Tree[x].fa;
Push_Down(y);Push_Down(x);
Tree[y].son[!c] = Tree[x].son[c];
if(Tree[x].son[c])Tree[Tree[x].son[c]].fa = y;
Tree[x].fa = Tree[y].fa;
if(Tree[y].fa)
Tree[Tree[y].fa].son[Tree[Tree[y].fa].son[1] == y] = x;
Tree[x].son[c] = y; Tree[y].fa = x;
Updata(y);Updata(x);
if(Tree[x].fa == 0)root = x;
}
inline void Splay(int x,int f){
Push_Down(x);
while(Tree[x].fa != f)
{
if(Tree[Tree[x].fa].fa == f)
Rotate(x,Tree[Tree[x].fa].son[0] == x);
else
{
int y = Tree[x].fa;
int kind = Tree[Tree[y].fa].son[1] == y;
if(Tree[y].son[kind] == x)
Rotate(y,!kind) , Rotate(x,!kind);
else
Rotate(x,kind) , Rotate(x,!kind);
}
}
if(f == 0)root = x;
Updata(x);
}
inline void Insert(int val,int x){
if(!x)
{
root = ++tot;
Tree[tot].key = val; Tree[tot].fa = 0;Tree[tot].num = Tree[tot].Size = 1;
return ;
}
if(Tree[x].key == val){
Tree[x].num++;
Tree[x].Size++;
Updata(x);
Splay(x,0);
return ;
}
if(!Tree[x].son[val>Tree[x].key]){
Tree[x].son[val>Tree[x].key] = ++tot;
Tree[tot].fa = x;Tree[tot].key = val;Tree[tot].num = Tree[tot].Size = 1;
Updata(x);
Splay(tot,0);
return ;
}
Insert(val, Tree[x].son[val>Tree[x].key]);
Updata(x);
}
inline void Select(int k,int f)
{
int tmp;
int t = root;
while(1)
{
Push_Down(t);
tmp = Tree[Tree[t].son[0]].Size;
if(tmp < k && k<= tmp+Tree[t].num)
break;
if(k<=tmp)
t = Tree[t].son[0];
else k -= tmp+Tree[t].num , t = Tree[t].son[1];
}
Splay(t,f);
}
inline void Traval(int x)
{
Push_Down(x);
if(Tree[x].son[0])Traval(Tree[x].son[0]);
Rep(i,Tree[x].num) printf("%d ",Tree[x].key);
if(Tree[x].son[1])Traval(Tree[x].son[1]);
}
int main()
{
int n,val;
LL m;
char cnt;
scanf("%d%lld",&n,&m);
int d=0,ans=0;
for(int i=1;i<=n;i++)
{
getchar();
scanf("%c %d",&cnt,&val);
if(cnt=='I' && val>=m)
Insert(val-d,root);
if(cnt=='A')d += val;
if(cnt=='S')
{
Insert(m+val-d,root);
d-=val;
ans += Tree[Tree[root].son[0]].Size;
if(Tree[root].num>1){
Tree[root].num--;
Tree[root].Size--;
Tree[root].son[0] = 0;
Updata(root);
}
else{
root = Tree[root].son[1];
Tree[root].fa = 0;
}
}
if(cnt=='F')
{
if(val>Tree[root].Size)
printf("%d\n",-1);
else
{
Select(Tree[root].Size-val+1,0);
printf("%d\n",Tree[root].key+d);
}
}
}
printf("%d\n",ans);
return 0;
}
此题还可以用树状数组来实现 ,参考了WCMG 大神的代码
/**************************************************************
Problem: 1503
User: 704035233
Language: C++
Result: Accepted
Time:308 ms
Memory:3616 kb
****************************************************************/
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 300010;
int a[maxn+10],c[maxn+10];
int n,m,x,now,ans,add,delta;
char com;
inline int read(){
static int r, sign;
static char c;
r = 0, sign = 1;
do c = getchar(); while(c != '-' && (c < '0' || c > '9'));
if( c == '-')sign = -1, c = getchar();
while( c >= '0' && c <='9') r = r*10 +(int)(c - '0'), c = getchar();
return sign * r;
}
void Add(int pos,int d)
{
while(pos<=maxn){
c[pos]+=d;
pos+=(pos&(-pos));
}
}
int find_kth(int x)
{
if(x<1)return -1;
int ans=0,cnt=0;
for(int i=18;i>=0;i--)
{
ans+=(1<<i);
if(ans>=maxn || cnt+c[ans]>=x)
ans-=(1<<i);
else cnt+=c[ans];
}
return ans+1+add-delta;
}
int main()
{
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
delta=10001;
add=com=0;
for(int i=1;i<=n;i++)
{
while(com!='I' && com !='A' && com!='S' && com != 'F')com=getchar();
x=read();
if(com=='I'&&x>=m){
Add(delta+x-add,1);
a[delta+x-add]++;
now++;
}
if(com=='A')add+=x;
if(com=='S'){
for(int j=delta+m-add;j<delta+m+x-add;j++)
if(j>0 && a[j]>0)
{
Add(j,-a[j]);
ans+=a[j];
now-=a[j];
a[j]=0;
}
add-=x;
}
if(com=='F')
{
printf("%d\n",find_kth(now-x+1));
}
com=0;
}
printf("%d\n",ans);
return 0;
}