给你n条l到r的线段。
在给你q个询问,每次给你一个x,可以切断线段,问你每次破坏了多少线段。
每次给出的要破坏的数不是单纯的x,而是上一次所有切断线段的编号的乘积和x的异或值,
求出要破坏的值y后,哪一条线段包含y,哪一条线段就被破坏掉。
每次询问输出此次破坏掉了几条线段。
最后还要输出所有线段最早是被第几次操作破坏掉的 | 没有被破坏(输出0)。
维护区间最小值和最大值即可。
并且由于我的写法每次都是跑到叶子结点,所以这些线段也不用排序。
代码里有详细的debug输出。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
#define lson rt<<1
#define rson rt<<1|1
#define MID int m = (l+r)/2;
struct node
{
int id,l,r;
} a[maxn];
int L[maxn],R[maxn];
vector<node>V;
void push_up(int rt)
{
L[rt] = min(L[lson],L[rson]);
R[rt] = max(R[lson],R[rson]);
}
void build(int rt,int l,int r)
{
//if(l>r)return;
if(l==r)
{
L[rt] = a[l].l;
R[rt] = a[l].r;
// cout<<"线段树 "<<rt<<" "<<a[l].l<<" "<<a[l].r<<" "<<l<<endl;
return;
}
MID
build(lson,l,m);
build(rson,m+1,r);
push_up(rt);
// cout<<"父节点 "<<rt<<" "<<L[rt]<<" "<<R[rt]<<" "<<l<<" "<<r<<endl;
}
int ans[maxn];
void update(int rt,int l,int r,int pos)
{
if(pos<L[rt]||pos>R[rt])return ;
if(l==r)
{
// cout<<"线段树 "<<rt<<" "<<a[l].l<<" "<<a[l].r<<" "<<l<<endl;
V.push_back(a[l]);
L[rt] = inf;
R[rt] =-inf;
return ;
}
MID
update(lson,l,m,pos);
update(rson,m+1,r,pos);
push_up(rt);
//cout<<"父节点 "<<rt<<" "<<L[rt]<<" "<<R[rt]<<" "<<l<<" "<<r<<endl;
}
int main()
{
int T;
cin>>T;
int cs = 0;
while(T--)
{
printf("Case #%d:\n",++cs);
int n,q;
cin>>n>>q;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id = i;
ans[i] = 0;
}
build(1,1,n);
long long res = 0;
for(int i=1; i<=q; i++)
{
V.clear();
int y ;
scanf("%d",&y);
long long yy = res^y;
// yy = y;
update(1,1,n,yy);
printf("%d\n",(int )V.size());
if(V.size()==0)res = 0;
else
{
res = 1;
for(node j:V)
{
res=(res*j.id)%mod;
ans[j.id] = i;
}
}
}
int top = 1;
for(int i=1; i<=n; i++)
{
if(top)top =0;
else printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}