Team Rocket 牛客网多校

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

用各线段的左端点离散化 建树时再将所有右端点有序地插入到线段树的叶节点 然后在pushup的过程中归并排序 这样对于每个查询 二分得到第一个小于等于x的左端点的位置p 然后查询[1,p]范围内有多少右端点大于等于x 还要看这些右端点代表的线段之前是否已经被抹除 数组标记即可 还有一个坑点就是 区间查询时如果没有一个右端点符合要求 由于查询区间乘积会返回一个1 而不是0 需要特判一下

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define M 998244353

struct node1
{
    ll id;
    ll l;
    ll r;
};

struct node2
{
    ll l;
    ll r;
    vector <ll> ary;
};

vector <ll> pre[200010];
node1 seg[200010];
node2 tree[800010];
int tmp[200010],ans1[200010],ans2[200010];
int n,q,len,flag;

bool cmpI(node1 n1,node1 n2)
{
    return n1.r<n2.r;
}
bool cmpII(node1 n1,node1 n2)
{
    return n1.id<n2.id;
}

void pushup(int cur)
{
    int i,j,l1,l2;
    l1=tree[2*cur].ary.size();
    l2=tree[2*cur+1].ary.size();
    i=0,j=0;
    while(i<l1&&j<l2)
    {
        if(seg[tree[2*cur].ary[i]].r<seg[tree[2*cur+1].ary[j]].r)
        {
            tree[cur].ary.push_back(tree[2*cur].ary[i]);
            i++;
        }
        else
        {
            tree[cur].ary.push_back(tree[2*cur+1].ary[j]);
            j++;
        }
    }
    while(i<l1)
    {
        tree[cur].ary.push_back(tree[2*cur].ary[i]);
        i++;
    }
    while(j<l2)
    {
        tree[cur].ary.push_back(tree[2*cur+1].ary[j]);
        j++;
    }
}

void build(int l,int r,int cur)
{
    int m,i;
    tree[cur].l=l;
    tree[cur].r=r;
    tree[cur].ary.clear();
    if(l==r)
    {
        for(i=0;i<pre[l].size();i++)
        {
            tree[cur].ary.push_back(pre[l][i]);
        }
        return;
    }
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
    pushup(cur);
}

ll query(int pl,int pr,int cnt,ll x,int cur)
{
    ll res;
    int i;
    if(pl<=tree[cur].l&&tree[cur].r<=pr)
    {
        res=1,i=tree[cur].ary.size()-1;
        while(i>=0)
        {
            if(seg[tree[cur].ary[i]].r<x) break;
            else
            {
                if(ans2[tree[cur].ary[i]]==0)
                {
                    ans1[cnt]++;
                    ans2[tree[cur].ary[i]]=cnt;
                    res=(res*tree[cur].ary[i])%M;
                    flag=1;
                }
                tree[cur].ary.erase(tree[cur].ary.begin()+i);
            }
            i--;
        }
        return res;
    }
    res=1;
    if(pl<=tree[2*cur].r) res=(res*query(pl,pr,cnt,x,2*cur))%M;
    if(pr>=tree[2*cur+1].l) res=(res*query(pl,pr,cnt,x,2*cur+1))%M;
    return res;
}

int main()
{
    ll gou,res,x;
    int t,cas,i,p;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d%d",&n,&q);
        for(i=1;i<=n;i++)
        {
            seg[i].id=i;
            scanf("%lld%lld",&seg[i].l,&seg[i].r);
            tmp[i]=seg[i].l;
        }
        sort(seg+1,seg+n+1,cmpI);
        sort(tmp+1,tmp+n+1);
        len=unique(tmp+1,tmp+n+1)-tmp-1;
        for(i=1;i<=len;i++) pre[i].clear();
        for(i=1;i<=n;i++)
        {
            p=lower_bound(tmp+1,tmp+len+1,seg[i].l)-tmp;
            pre[p].push_back(seg[i].id);
        }
        sort(seg+1,seg+n+1,cmpII);
        build(1,len,1);
        memset(ans1,0,sizeof(ans1));
        memset(ans2,0,sizeof(ans2));
        gou=0;
        for(i=1;i<=q;i++)
        {
            scanf("%lld",&x);
            x^=gou;
            if(x<tmp[1]) gou=0;
            else
            {
                p=upper_bound(tmp+1,tmp+len+1,x)-tmp-1;
                flag=0;
                gou=query(1,p,i,x,1);
                if(flag==0) gou=0;
            }
        }
        printf("Case #%d:\n",cas);
        for(i=1;i<=q;i++)
        {
            printf("%d\n",ans1[i]);
        }
        for(i=1;i<=n;i++)
        {
            printf("%d",ans2[i]);
            if(i<n) printf(" ");
            else printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/81427898
今日推荐