牛客网暑期ACM多校训练营(第六场)I:Team Rocket(线段树)

链接:https://www.nowcoder.com/acm/contest/144/I

时间限制:C/C++ 4秒,其他语言8秒
空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld
题目描述
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. x i = ( y i ( r e s i 1 m o d 998244353 ) ) , 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 × 10 5 .
  • 10 9 l i r i 10 9 .
  • 10 9 x i 10 9 .

输出描述:
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 i 的最小值和右端点 r i 的最大值,以及该区间内的未被摧毁的线段数目。最后所有的叶子节点存储该线段的下标。

如果对所有线段按 l i 从小到大排个序会比不排序快个1s左右。
(也可能是牛课的评测姬变换无常。。)

因为最多摧毁n条线段,所以每次我们可以暴力查询哪些线段被摧毁,然后计算答案。

#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
const int MOD=998244353;
const int INF=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
struct data{int l,r,id;}a[MAX];
int cmp(const data& p,const data& q){return p.l<q.l;}
struct lenka
{
    int l,r;
    int x,y,id;//x代表最小的左端点,y是最大的右端点,id是线段下标
    int sum;   //sum记录区间内未被摧毁的线段数目
}A[MAX<<2];
int ans[MAX];
vector<int>p;
void build(int k,int l,int r)
{
    A[k].l=l,A[k].r=r;
    if(l==r)
    {
        A[k].sum=1;
        A[k].id=a[r].id;
        A[k].x=a[r].l;
        A[k].y=a[r].r;
        return;
    }
    build(2*k,l,(l+r)/2);
    build(2*k+1,(l+r)/2+1,r);
    A[k].y=max(A[2*k].y,A[2*k+1].y);
    A[k].x=min(A[2*k].x,A[2*k+1].x);
    A[k].sum=A[2*k].sum+A[2*k+1].sum;
}
void ask(int k,int x)
{
    if(A[k].sum==0)return;
    if(A[k].x>x||A[k].y<x)return;
    if(A[k].l==A[k].r)
    {
        p.push_back(A[k].id);
        A[k].sum=0;
        return;
    }
    ask(2*k,x);
    ask(2*k+1,x);
    A[k].sum=A[2*k].sum+A[2*k+1].sum;
}
int main()
{
    int T,cas=1;
    cin>>T;
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d%d",&a[i].l,&a[i].r);
        for(int i=1;i<=n;i++)a[i].id=i,ans[i]=0;
        sort(a+1,a+n+1,cmp);
        build(1,1,n);
        printf("Case #%d:\n",cas++);
        ll res=0;
        for(int j=1;j<=m;j++)
        {
            int x;
            scanf("%d",&x);
            x^=res;
            p.clear();
            ask(1,x);
            printf("%d\n",p.size());
            if(p.size()==0)
            {
                res=0;
                continue;
            }
            res=1;
            for(int i=0;i<p.size();i++)res=res*p[i]%MOD;
            for(int i=0;i<p.size();i++)ans[p[i]]=j;
        }
        for(int i=1;i<=n;i++)printf("%d%c",ans[i],i==n?'\n':' ');
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/81449232