您的位置:首页 > 其它

[分块 块的分裂 || 替罪羊树套线段树] BZOJ 3065 带插入区间K小值

2016-12-25 14:10 309 查看
省选时收了分块大师的教导

于是用分块过了这题 当时竟然没有发上来

具体快忘完了 只是记得分裂什么的

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef pair<int,int> abcd;

inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline void read(char &x)
{
for (x=nc();!(x=='Q' || x=='M' || x=='I');x=nc());
}

inline double Log(int x){
return log(x)/log(2);
}

int n,lastans;
int inum[35005];
int B,cnt;
int nxt[1005],tot[1005];
int a[1005][1005],b[1005][1005];

inline abcd kth(int k){
for (int i=1;i;i=nxt[i])
{
if (!nxt[i] && k>tot[i])
return abcd(i,k);
if (k>tot[i])
k-=tot[i];
else
return abcd(i,k);
}
}

int l,r,K,x,val,ipos,idx;
abcd lp,rp,pos;

inline bool check(int mid,int K){
int ret=0;
if (lp.first==rp.first)
{
for (int i=lp.second;i<=rp.second;i++)
if (a[lp.first][i]<=mid)
ret++;
return ret>=K;
}
for (int i=lp.second;i<=tot[lp.first];i++)
if (a[lp.first][i]<=mid)
ret++;
for (int i=1;i<=rp.second;i++)
if (a[rp.first][i]<=mid)
ret++;
for (int i=nxt[lp.first];i!=rp.first;i=nxt[i])
ret+=upper_bound(b[i]+1,b[i]+tot[i]+1,mid)-b[i]-1;
return ret>=K;
}

inline void Query()
{
read(l); read(r); read(K);
l^=lastans; r^=lastans; K^=lastans;
lp=kth(l),rp=kth(r);
int L=-1,R=70000,MID;
while (L+1<R)
if (check(MID=(L+R)>>1,K))
R=MID;
else
L=MID;
printf("%d\n",lastans=R);
// lastans=0;
}

inline void Modify()
{
int last;
read(x); read(val);
x^=lastans; val^=lastans;
pos=kth(x);
idx=pos.first;
last=a[idx][pos.second];
a[idx][pos.second]=val;
ipos=lower_bound(b[idx]+1,b[idx]+tot[idx]+1,last)-b[idx];
b[idx][ipos]=val;
while (ipos-1>=1 && b[idx][ipos]<b[idx][ipos-1])
swap(b[idx][ipos],b[idx][ipos-1]),ipos--;
while (ipos+1<=tot[idx] && b[idx][ipos]>b[idx][ipos+1])
swap(b[idx][ipos],b[idx][ipos+1]),ipos++;
}

inline void Death(int p)
{
++cnt;
for (int i=B+1;i<=tot[p];i++)
a[cnt][++tot[cnt]]=a[p][i],b[cnt][tot[cnt]]=a[cnt][tot[cnt]],a[p][i]=0;
sort(b[cnt]+1,b[cnt]+tot[cnt]+1);
tot[p]-=B;
for (int i=1;i<=tot[p];i++)
b[p][i]=a[p][i];
sort(b[p]+1,b[p]+tot[p]+1);
nxt[cnt]=nxt[p]; nxt[p]=cnt;
}

inline void Insert()
{
read(x); read(val);
x^=lastans; val^=lastans;
pos=kth(x);
idx=pos.first;
for (int i=tot[idx];i>=pos.second;i--)
a[idx][i+1]=a[idx][i];
a[idx][pos.second]=val;
b[idx][ipos=++tot[idx]]=val;
while (ipos-1>=1 && b[idx][ipos]<b[idx][ipos-1])
swap(b[idx][ipos],b[idx][ipos-1]),ipos--;
if (tot[idx]>=2*B)
Death(idx);
}

int main()
{
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
int Q;
char order;
read(n);
for (int i=1;i<=n;i++) read(inum[i]);
B=sqrt(n); cnt=(n-1)/B+1;
for (int i=1;i<=n;i++)
{
ipos=(i-1)/B+1;
a[ipos][++tot[ipos]]=inum[i];
b[ipos][tot[ipos]]=inum[i];
}
for (int i=1;i<=cnt;i++)
nxt[i]=i+1;
nxt[cnt]=0;
for (int i=1;i<=cnt;i++)
sort(b[i]+1,b[i]+tot[i]+1);
read(Q);
while (Q--)
{
read(order);
if (order=='Q')
Query();
else if (order=='M')
Modify();
else if (order=='I')
Insert();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: