题目链接:点击这里
解题思路:
这题还不让离线真的是,不过它把关键放在了删除上面,这就是一个区间被覆盖之后就会被删除了。那么这个问题就可以用O(nlogn)来解决了.用左端点l来离散建立线段树,右端点r作为区间值。线段树维护区间最大值.
那么我们去查询x的时候实际上就是在线段树[1,x]中去查找值不小于x的点,然后把它删除,之后改变他的值为负无穷,因为他已经被删除了。这就是为什么可以用O(nlogn)来解决。那么要是区间最大值小于x,这个区间就不同区看了,一定没有满足条件的。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mp(a,b) make_pair(a,b)
using namespace std;
const int mx = 2e5 + 10;
const int mod = 998244353;
typedef long long ll;
int n,m,pos[mx<<2],big[mx<<2];
int cnt,ret,ans[mx],res;
struct node
{
int l,r;
int p;
bool operator < (node A)const
{
return l < A.l;
}
}s[mx];
void build(int l,int r,int rt)
{
if(l==r){
big[rt] = s[l].r;
pos[rt] = s[l].p;
ans[l] = 0;
return ;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
big[rt] = max(big[rt<<1],big[rt<<1|1]);
}
void update(int R,int v,int l,int r,int rt)
{
if(big[rt]<v) return ;
if(l==r){
++cnt;
big[rt] = -inf;
res = (1ll*res*pos[rt])%mod;
ans[pos[rt]] = ret;
return ;
}
int mid = (l+r)>>1;
update(R,v,lson);
if(R>mid) update(R,v,rson);
big[rt] = max(big[rt<<1],big[rt<<1|1]);
}
int main()
{
int t,cas =1;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&s[i].l,&s[i].r);
s[i].p = i;
}
sort(s+1,s+1+n);
build(1,n,1);
int y;res = 0;
printf("Case #%d:\n",cas++);
for(int i=1;i<=m;i++){
scanf("%d",&y);
y = (y^res);
cnt = 0,ret = i,res = 1;
int R = upper_bound(s+1,s+1+n,(node){y,0,0}) - s - 1;
if(R) update(R,y,1,n,1);
if(!cnt) res = 0;
printf("%d\n",cnt);
}
for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' ');
}
return 0;
}