牛客多校第六场 I Team Rocket(线段树)

链接:https://www.nowcoder.com/acm/contest/144/I
来源:牛客网
 

题目描述

There are n trains running between Kanto and Johto region. Assuming the railway is a number line, the i-th train travels from coordinate li to coordinate ri (both inclusive).

One day, m Team Rocket members invaded the railway system successfully. The i-th Team Rocket member was going to destroy the transportation hub with coordinate xi. Once a transportation hub within the driving range of a train is destroyed, the train's itinerary will be canceled immediately.

Giovanni wants to know how many train trips will be firstly canceled after each attack.

After all the attacks finished, for each train Giovanni needs to know that in which attack its itinerary was firstly canceled, or it was unaffected at all.

输入描述:

The input starts with one line containing exactly one integer T, which is the number of test cases.

For each test case, the first line contains two integers n and m, indicating the number of trains and the number of Team Rocket members.

Each of the next n lines contains 2 integers li and ri, indicating the driving range of the i-th train.

Each of the next m lines contains exactly one integer yi. , where xi is the transportation hub that Team Rocket members would destroy in the i-th attack, resi-1 is the product of the indexes of trips cancelled by the (i-1)-th attack and  means exclusive or. 

If no such trip exists, resi-1 is considered to be 0.

- 1 ≤ T ≤ 5.
- 1 ≤ n,m ≤ 2 x 105.
- -109 ≤ li ≤ ri ≤ 109.
- -109 ≤ xi ≤ 109.

输出描述:

For each test case, output one line "Case #x:" first, where x is the test case number (starting from 1).

Then output m lines, each line of which contains exactly one integer, indicating the number of train trips firstly canceled after the i-th attack.

Finally output one line, containing n integers, where the i-th integer is the time when the i-th train trip is firstly canceled or 0 if it is not affected.

示例1

输入

复制

1
3 4
1 3
2 6
-999 1000000000
-1000
1
5
2

输出

复制

Case #1:
0
2
1
0
2 3 2

题目大意:在两个地方之间有n辆火车,每辆火车有个运行区间[l,r]。接下来会有m次轰炸,每次会对一个坐标为x的地方进行轰炸,如果x正好在某辆火车的运行区间之间,那么这辆火车将会停运。现在要你求出每次操作会使得多少辆火车第一次停运,以及每辆火车是在第几次轰炸后第一次停运,如果没有停运就输出0。

题目思路:我们可以考虑把两地看成是一条直线,由于每辆火车都有一个运行区间[l,r],我们可以把每辆火车按区间的左端点 l 从小到大进行排序,然后借助线段树来维护区间的右端点 r的最大值。对于每次轰炸的x,只会对区间[l,r]满足 l<=x<=r的火车产生影响,所以我们可以先二分找出满足l<=x的区间,再用线段树进行更新所有r>=x的区间,由于每个点都只需要记录第一次停运产生的影响,所以一辆火车一旦被停运了,我们就可以把其右区间设为-inf,这样就不会重复产生贡献了。在线段树更新的过程,一但一个区间右端点的最大值小于x,就不用继续往下更新了,可以节省大量的时间。这样均摊下来的总时间复杂度应该是O(nlogn)。

具体实现看代码:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lowbit(x) x&-x
#define pb push_back
#define MP make_pair
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define fuck(x) cout<<"["<<x<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
typedef pair<ll,ll>pll;
typedef vector<int> VI;
const int MX=2e5+7;
const int mod=998244353;
const int inf=0x3f3f3f3f;

int T,n,q;
ll res;
int ret;
struct node{
	int l,r,id;

	bool operator<(const node &A)const{
		if(l==A.l) return r<A.r;
		return l<A.l;
	}
}a[MX];
int p[MX];
int ans[MX];
int mxr[MX<<2];
void push_up(int rt){
	mxr[rt]=max(mxr[rt<<1],mxr[rt<<1|1]);
}
void build(int l,int r,int rt){
	mxr[rt]=0;
	if(l==r){
		mxr[rt]=a[l].r;
		return;
	}
	int m=(l+r)>>1;
	build(lson);
	build(rson);
	push_up(rt);
}
void update(int L,int R,int x,int index,int l,int r,int rt){
	if(L>R || l>r) return; 
	if(mxr[rt]<x) return;
	if(l==r){
		mxr[rt]=-inf;
		ret++;res=(res*a[l].id)%mod;
		ans[a[l].id]=index;
		return;
	}
	int m=(l+r)>>1;
	if(L<=m) update(L,R,x,index,lson);
	if(R>m) update(L,R,x,index,rson);
	push_up(rt);
}

int main(){
	//FIN;
	cin>>T;
	for(int cas=1;cas<=T;cas++){
		clr(ans);
		scanf("%d%d",&n,&q);
		for(int i=1;i<=n;i++){
			scanf("%d%d",&a[i].l,&a[i].r);
			p[i]=a[i].l;
			a[i].id=i;
		}
		sort(a+1,a+n+1);
		sort(p+1,p+n+1);
		build(1,n,1);
		res=ret=0;
		int x;
		printf("Case #%d:\n",cas);
		for(int i=1;i<=q;i++){
			scanf("%d",&x);
			x^=res;
			int pos=upper_bound(p+1,p+n+1,x)-p;pos--;
			res=1;ret=0;
			update(1,pos,x,i,1,n,1);
			printf("%d\n",ret);
			if(ret==0) res=0;
		}
		for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' ');
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Lee_w_j__/article/details/81428262