链接
题解
自闭了一下午,难受,全在调试splay板子
分析题目,发现:
如果一个队本来就打铁,过了题之后还打铁,那么我压根不用管
如果一个队本来就有牌,过了题之后还有牌,那么我需要维护下新的排名序列
如果一个队本来打铁,过题之后有牌了,那我需要把他从“打铁集合”当中删掉,然后加入“有牌集合”
因为打铁的队伍我并不关心他们的排名,所以用一个树状数组,以序号为下标维护下前缀和就行了。
而有牌的队伍,我需要维护一下他们的先后关系,所以需要一个平衡树
代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
struct Splay
{
typedef int T;
int root, cnt[maxn], ch[maxn][2], f[maxn], size[maxn], tot;
T v[maxn];
void clear()
{
for(int i=1;i<=tot;i++)f[i]=cnt[i]=size[i]=ch[i][0]=ch[i][1]=0;
root=tot=0;
}
void pushup(int x)
{
size[x]=cnt[x]+size[ch[x][0]]+size[ch[x][1]];
}
int get(int x){return ch[f[x]][1]==x;}
void rotate(int x)
{
int y=f[x], z=f[y], t=get(x);
f[ch[x][!t]]=y, ch[y][t]=ch[x][!t];
f[x]=z, ch[z][get(y)]=x;
f[y]=x, ch[x][!t]=y;
pushup(y);
pushup(x);
}
void splay(int x, int goal=0)
{
while(f[x]!=goal)
{
if(f[f[x]]!=goal)rotate(get(x)==get(f[x])?f[x]:x);
rotate(x);
}
if(!goal)root=x;
}
int insert(T x)
{
int now=root, pp=0;
while(now and v[now]!=x)
{
pp = now;
now = ch[now][x>v[now]];
}
if(now)cnt[now]++;
else
{
cnt[now=++tot]=1;
v[now]=x;
f[now]=pp;
ch[pp][x>v[pp]]=now;
}
splay(now);
return now;
}
int find(T x)
{
int now;
for(now=root;v[now]!=x;now=ch[now][x>v[now]]);
splay(now);
return now;
}
int kth(int k)
{
int now=root, lsz, rsz;
while(true)
{
lsz = size[ch[now][0]], rsz = size[ch[now][1]];
if(lsz+cnt[now]>=k)
{
if(lsz<k)return now;
else now=ch[now][0];
}
else
{
k -= lsz+cnt[now];
now = ch[now][1];
}
}
}
int pre(int x)
{
splay(x);
int now;
for(now=ch[x][0];ch[now][1];now=ch[now][1]);
splay(now);
return now;
}
int suc(int x)
{
splay(x);
int now;
for(now=ch[x][1];ch[now][0];now=ch[now][0]);
splay(now);
return now;
}
void erase(int x)
{
if(cnt[x]>1){cnt[x]--;splay(x);return;}
int p=pre(x), s=suc(x);
splay(p), splay(s,p);
ch[s][0]=f[x]=0;
pushup(s), pushup(p);
}
}splay;
struct BIT
{
ll bit[maxn], n;
void init(int N){n=N;for(int i=1;i<=n;i++)bit[i]=0;}
ll lowbit(ll x){return x&(-x);}
void add(ll pos, ll v)
{
for(;pos<=n;pos+=lowbit(pos))bit[pos]+=v;
}
ll sum(ll pos)
{
ll ans(0);
for(;pos;pos-=lowbit(pos))ans+=bit[pos];
return ans;
}
}bit;
int main()
{
int T=read();
while(T--)
{
int n=read(), i;
vector<ll> p(n+5), num(n+5), q(n+5);
int fe = n*6/10+1;
splay.clear();
int last = splay.insert(-iinf);
int ed = splay.insert(iinf);
bit.init(n);
rep(i,1,n)
{
p[i]=read();
if(p[i]>=fe)
{
bit.add(i,+1);
num[i]=-1;
}
else
{
q[p[i]]=i;
}
}
rep(i,1,fe-1)
{
splay.splay(last);
splay.splay(ed,last);
int x = ++splay.tot;
num[q[i]] = x;
splay.v[x] = q[i];
splay.cnt[x] = splay.size[x] = 1;
splay.f[x] = ed;
splay.ch[ed][0] = x;
splay.pushup(ed);
splay.pushup(last);
last = x;
}
int Q=read();
while(Q--)
{
int op=read(), x=read(), y=read();
if(op==2)
{
printf("%lld\n",bit.sum(y)-bit.sum(x-1));
}
else
{
if(y<fe)
{
if(num[x]!=-1)
{
splay.erase(num[x]);
num[x] = -1;
}
else
{
bit.add(x,-1);
}
int pre = splay.kth(y), suc = splay.suc(pre), t = ++splay.tot;
splay.splay(pre), splay.splay(suc,pre);
num[x] = t;
splay.v[t] = x;
splay.cnt[t] = splay.size[t] = 1;
splay.f[t] = suc;
splay.ch[suc][0] = t;
splay.pushup(suc);
splay.pushup(pre);
if(fe>1 and splay.size[splay.root]==fe+2)
{
int datie = splay.kth(fe+1);
if(splay.v[datie]>n)de(n),de(datie),de(fe),de(splay.size[splay.root]);
num[ splay.v[datie] ] = -1;
bit.add(splay.v[datie],+1);
splay.erase( datie );
}
}
}
}
}
return 0;
}