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

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

题意:

n个区间[l,r],m个操作:给数b,删去包含点b^res的区间,记录每个区间i第几次操作时被删去,每次操作删去的区间数。 
res是上次删除的区间编号的乘积%998244353,如果上次未删区间,即res为0。

思路:

我们可以将线段按照l来排序,然后再来构造线段树,找到区间右端点的最大值,如果删除的点比R还大,说明跟这个区间无关,

否则删除这个区间,删除的这个区间R改为-inf。

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=998244353;
const int maxn=2e5+10;
const int inf=0x3f3f3f3f;
vector<int>v;
int n,m;
struct node
{
    int l,r,id;
}a[maxn];
struct Node
{
    int id,val;
}t[maxn*4];
ll y,res;
int cnt,pos;
int ans[maxn];
bool cmp(node a,node b)
{
   return a.l<b.l;
}
void build(int x,int l,int r)
{
    if(l>r)return;
    if(l==r)
    {
        t[x].val=a[l].r;
        t[x].id=a[l].id;
        return;
    }
    int mid=(l+r)/2;
    build(x*2,l,mid);
    build(x*2+1,mid+1,r);
    t[x].val=max(t[x*2].val,t[x*2+1].val);
}
void query(int x,int l,int r,int num)
{
    if(l>r||y>t[x].val)return;
    if(l==r)
    {
        cnt++;
        t[x].val=-inf;
        res=(res*t[x].id)%mod;
        ans[t[x].id]=num;
        return;
    }
    int mid=(l+r)/2;
    query(x*2,l,mid,num);
    if(pos>=mid+1)
        query(x*2+1,mid+1,r,num);
    t[x].val=max(t[x*2].val,t[x*2+1].val);
}
int main()
{
    int T;
    scanf("%d",&T);
    int cas=0;
    while(T--)
    {
        v.clear();
        scanf("%d%d",&n,&m);
        memset(ans,0,sizeof(ans));
        printf("Case #%d:\n",++cas);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a[i].l,&a[i].r);
            a[i].id=i;
            v.push_back(a[i].l);
        }
        sort(a+1,a+1+n,cmp);
        sort(v.begin(),v.end());
        build(1,1,n);
        res=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%lld",&y);
            y^=res;
            cnt=0;
            res=1LL;
            pos=upper_bound(v.begin(),v.end(),y)-v.begin();
            if(pos>0)
                query(1,1,n,i);
            if(cnt==0)
                res=0;
            printf("%d\n",cnt);
        }
        for(int i=1;i<=n;i++)
        {
            if(i>1)printf(" ");
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81571155