Description
数轴表示一条铁路,给出该铁路 n n n次列车的运行区间 [ l i , r i ] [l_i,r_i] [li,ri],现在有 m m m个炸弹会炸毁铁路,其中第 i i i个炸弹会炸毁 x i x_i xi处的火车站,所有经过该火车站的列车均不能继续行驶,问每次炸毁一个火车站之后所影响的列车数(该列车之前可以行驶但炸毁后不能行驶),最后输入每趟列车是被哪个炸弹影响的
Input
第一行一整数 T T T表示用例组数,每组用例首先输入两个整数 n , m n,m n,m,之后 n n n行每行输入两个整数 l i , r i l_i,r_i li,ri表示第 i i i趟列车的始发站和终点站,最后 m m m行每行输入一整数 y i y_i yi,其中 x 1 = y 1 x_1=y_1 x1=y1, x i = ( y i ⊕ ( r e s i − 1 m o d 998244353 ) ) x_i=(y_i\oplus (res_{i-1}\ mod\ 998244353)) xi=(yi⊕(resi−1 mod 998244353)), r e s i − 1 res_{i-1} resi−1表示第 i − 1 i-1 i−1次袭击后被影响的列车编号乘积
( 1 ≤ T ≤ 5 , 1 ≤ n , m ≤ 2 ⋅ 1 0 5 , − 1 0 9 ≤ l i ≤ r i ≤ 1 0 9 , − 1 0 9 ≤ y i ≤ 1 0 9 ) (1\le T\le 5,1\le n,m\le 2\cdot 10^5,-10^9\le l_i\le r_i\le 10^9,-10^9\le y_i\le 10^9) (1≤T≤5,1≤n,m≤2⋅105,−109≤li≤ri≤109,−109≤yi≤109)
Output
输出每次袭击影响的列车数量,最后输出 n n n个整数表示每趟列车是被哪个炸弹影响的,如果该趟列车最后依旧能够行驶则输出 0 0 0
Sample Input
1
3 4
1 3
2 6
-999 1000000000
-1000
1
5
2
Sample Output
Case #1:
0
2
1
0
2 3 2
Solution
将所有区间左端点离散化建线段树,线段树每个节点用一个 v e c t o r vector vector存下所有左端点位于该区间的右端点,将所有右端点排序,那么每次区间合并时用归并排序可以使得建树复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),且树上所有节点的 v e c t o r vector vector内元素至多 n l o g n nlogn nlogn个,每次对于一个爆炸点 y y y,更新区间 [ 1 , y ] [1,y] [1,y],在每个区间的 v e c t o r vector vector里从后往前删右端点不小于 y y y的元素,如果该区间是第一次被删除则记录答案,由于删除是 O ( 1 ) O(1) O(1)的,每个元素只会被删除一次,故总时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int,int>P;
#define maxn 200005
vector<int>V[maxn<<2],v[maxn];
int T,Case=1,n,m,a[maxn],ll[maxn],rr[maxn],ans[maxn];
bool cmp(int x,int y)
{
return rr[x]<rr[y];
}
#define ls (t<<1)
#define rs ((t<<1)|1)
void build(int l,int r,int t)
{
V[t].clear();
if(l==r)
{
for(int i=0;i<v[l].size();i++)V[t].push_back(v[l][i]);
return ;
}
int mid=(l+r)/2;
build(l,mid,ls);
build(mid+1,r,rs);
int i=0,j=0;
while(i<V[ls].size()&&j<V[rs].size())
{
if(rr[V[ls][i]]<=rr[V[rs][j]])V[t].push_back(V[ls][i++]);
else V[t].push_back(V[rs][j++]);
}
while(i<V[ls].size())V[t].push_back(V[ls][i++]);
while(j<V[rs].size())V[t].push_back(V[rs][j++]);
}
#define mod 998244353
int mul(int x,int y)
{
long long z=1ll*x*y;
return z-z/mod*mod;
}
int res;
int update(int L,int R,int l,int r,int t,int y,int id)
{
int cnt=0;
if(L<=l&&r<=R)
{
while(V[t].size()&&rr[V[t].back()]>=y)
{
if(!ans[V[t].back()])
{
ans[V[t].back()]=id;
cnt++;
res=mul(res,V[t].back());
}
V[t].pop_back();
}
return cnt;
}
int mid=(l+r)/2;
if(L<=mid)cnt+=update(L,R,l,mid,ls,y,id);
if(R>mid)cnt+=update(L,R,mid+1,r,rs,y,id);
return cnt;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&ll[i],&rr[i]);
a[i]=ll[i];
}
sort(a+1,a+n+1);
int tot=unique(a+1,a+n+1)-a-1;
for(int i=1;i<=tot;i++)v[i].clear();
for(int i=1;i<=n;i++)
{
ll[i]=lower_bound(a+1,a+tot+1,ll[i])-a;
v[ll[i]].push_back(i);
}
for(int i=1;i<=tot;i++)sort(v[i].begin(),v[i].end(),cmp);
build(1,tot,1);
int pre=0;
memset(ans,0,sizeof(ans));
printf("Case #%d:\n",Case++);
for(int i=1;i<=m;i++)
{
int y,num=0;
scanf("%d",&y);
if(i>1)y^=pre;
int x=upper_bound(a+1,a+tot+1,y)-a-1;
res=1;
if(x)num=update(1,x,1,tot,1,y,i);
if(!num)res=0;
pre=res;
printf("%d\n",num);
}
for(int i=1;i<=n;i++)printf("%d%c",ans[i],i==n?'\n':' ');
}
return 0;
}