链接
题解
把区间按照左端点排序
然后线段树按照这个拍好的顺序,维护右端点最大值
每次查询,就是先通过在左端点序列上二分,确定我要查找的前缀
然后不停的查找前最大值,如果最大值大于 x x x,我就去这个最大值对应的叶子节点,找到那个区间,讲这个区间给删掉(设为无穷小)
代码
#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 400010
#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 SegmentTree
{
int L[maxn<<2], R[maxn<<2];
void build(ll o, ll l, ll r)
{
ll mid(l+r>>1);
L[o]=l, R[o]=r;
s[o].clear();
if(l==r)return;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
}
void Add(ll o, ll l, ll r, ll v)
{
ll mid(L[o]+R[o]>>1);
if(l<=L[o] and r>=R[o]){s[o].em(v);return;}
if(l<=mid)Add(o<<1,l,r,v);
if(r>mid)Add(o<<1|1,l,r,v);
}
void kesu(ll o, ll l, ll r, ll v)
{
ll mid = (L[o]+R[o]>>1);
if(l<=L[o] and R[o]<=r){s[o].erase(v);return;}
if(l<=mid)kesu(o<<1,l,r,v);
if(r>mid)kesu(o<<1|1,l,r,v);
}
void q(ll o, ll pos, vector<ll>& v)
{
ll mid = (L[o]+R[o]>>1);
for(auto x:s[o])v.emb(x);
if(L[o]==R[o])return;
if(pos<=mid)q(o<<1,pos,v);
else q(o<<1|1,pos,v);
}
}segtree;
struct Lisan
{
int tmp[maxn], tot;
void clear(){tot=0;}
void insert(int x){tmp[++tot]=x;}
void run()
{
sort(tmp+1,tmp+tot+1);
tot=unique(tmp+1,tmp+tot+1)-tmp-1;
}
void lisan(ll* a, int len)
{
for(int i=1;i<=len;i++)a[i]=lower_bound(tmp+1,tmp+tot+1,a[i])-tmp;
}
int lisan(int x)
{
return lower_bound(tmp+1,tmp+tot+1,x)-tmp;
}
}ls;
ll l[maxn], r[maxn], ans[maxn];
vector<ll> v;
int main()
{
ll T=read(), kase;
rep(kase,1,T)
{
printf("Case #%lld:\n",kase);
ll n=read(), m=read(), i, num, last=0;
ls.clear();
rep(i,1,n)
{
l[i]=read(), r[i]=read();
ls.insert(l[i]);
ls.insert(r[i]+1);
ans[i]=0;
}
ls.run();
segtree.build(1,1,ls.tot);
ls.lisan(l,n);
rep(i,1,n)
{
r[i] = upper_bound( ls.tmp+1, ls.tmp + ls.tot + 1, r[i] ) - ls.tmp - 1;
}
rep(i,1,n)segtree.Add(1,l[i],r[i],i);
rep(num,1,m)
{
ll x=read()^last;
x = upper_bound( ls.tmp+1, ls.tmp+ls.tot+1, x ) - ls.tmp - 1;
if(x==0)
{
printf("0\n");
continue;
}
v.clear();
segtree.q(1,x,v);
if(v.size())last=1;
else last=0;
for(auto t:v)
{
segtree.kesu(1,l[t],r[t],t);
ans[t]=num;
last*=t;
last%=998244353;
}
printf("%d\n",v.size());
}
rep(i,1,n)printf("%lld ",ans[i]);
putchar(10);
}
return 0;
}