http://www.elijahqi.win/archives/2762
题意:1~n号插线板 每个插线板有一个存在的时间每个人有一个使用时间 问插在哪个插线板可以挪动次数最少 每次一个插线板的插入和取走都只会对他后面的一个产生影响
将每个人的操作拆成两个 然后预处理succ表示我操作这个之后会对后面的哪个插线板产生挪动次数的贡献
然后分块 表示这段时间之前到所有点的区间挪动最优值处理出来 针对每个操作使用可持久化块状数组维护 (查询o(1))查询的时候因为我块前面的已经处理出来了 那么显然我只需要考虑我这个块到我这个人需要时间的这些区域里的最小值 我已在sqrt的时间处理出来
#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
#define bk 350
#define inf 0x3f3f3f3f
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x*f;
}
struct Persistent_block_array{
int *p[N/bk+2];
inline void add(int x){
const int bl=x/bk;
int *t=new int[bk];
if (p[bl]) memcpy(t,p[bl],sizeof(int)*bk);else memset(t,0,sizeof(int)*bk);
++t[x%bk];p[bl]=t;
}
inline int query(int x){
const int bl=x/bk;return p[bl]?p[bl][x%bk]:0;
}
}arr[N];
struct node{
int id,op,time;
}opt[N];
inline bool cmp(const node &a,const node &b){return a.time<b.time;}
set<int> s;
int succ[N],pre_ans[400][N],sum[N],n,m,q,type,L[N],R[N],last_ans;
int main(){
freopen("t3.in","r",stdin);
// freopen("t3.out","w",stdout);
n=read();m=read();q=read();type=read();int cnt=0;
for (int i=1;i<=n;++i){
L[i]=read();R[i]=read();opt[++cnt]=(node){i,1,L[i]};opt[++cnt]=(node){i,0,R[i]};
}sort(opt+1,opt+(n=cnt)+1,cmp);
for (int i=1;i<=n;++i){
if (!opt[i].op) s.erase(opt[i].id);set<int>::iterator it;
it=s.lower_bound(opt[i].id);if (it!=s.end()) succ[i]=*it;
if (opt[i].op) s.insert(opt[i].id);
}
for (int i=1;i<=n;++i){arr[i]=arr[i-1];
if (!opt[i-1].op&&succ[i-1]) arr[i].add(succ[i-1]);
if (opt[i].op&&succ[i]) arr[i].add(succ[i]);
}
for (int j=1;j<=n;j+=bk){
memset(sum,0,sizeof(sum));
for (int i=j;i<=n;++i) if (succ[i]) ++sum[succ[i]];int mn=inf;
for (int i=n;i>=j;--i){int id=opt[i].id,su=succ[i];
if(!opt[i].op&&L[id]<=j) mn=min(mn,sum[id]);
if (!opt[i].op&&su){
--sum[su];if (L[su]<=j) mn=min(mn,sum[su]);
}pre_ans[j/bk][i]=mn;
if (opt[i].op&&su){
--sum[su];if (L[su]<=j) mn=min(mn,sum[su]);
}
}
}
for (int i=1;i<=q;++i){
int l=read()^last_ans,r=read()^last_ans;int bl=(l-1)/bk,mn=pre_ans[bl][r];
for (int j=bl*bk+1;j<=l;++j){
const int id=opt[j].id,su=succ[j];
if (R[id]>=r) mn=min(mn,arr[r].query(id)-arr[l].query(id));
if (R[su]>=r) mn=min(mn,arr[r].query(su)-arr[l].query(su));
}last_ans=mn;
printf("%d\n",last_ans!=inf?last_ans:-1);
last_ans=type==0?0:last_ans;last_ans=last_ans==inf?0:last_ans;
}
return 0;
}