• 牛客NOIP暑期七天营-普及组2D


    链接:https://ac.nowcoder.com/acm/contest/926/D
    来源:牛客网

    在一维坐标系中,给定 n条有颜色的线段,第 i条线段的左右端点分别为 li ri,此外它的颜色为 ci

    给定m个查询,每个查询给定一个区间 [a,b],需要求出这个区间完全包含的线段中有多少种不同颜色的线段。

    题解:说是普及组,还是需要一些水平的。简单的版本可以参考:最开始学主席树的时候的题目:SPOJ:D-query
    这些说起来之前那个题也可以这样做的。 即是离线操作,把询问和线段一起按右端点排序,然后依次处理,对于同一种颜色,树状数组里面保存最右边的那个。
    这样保证了包含的的优先级,而且只统计了依次。
    (copy了一份初中生的代码。
    #include<bits/stdc++.h>
    using namespace std;
    const int M = 2000001;
    int C,n,m,k,a[M],b[M],c[M],cnt,res[M];
     
    void add(int x,int y)
    {
        for(int i=x;i<=C+1;i+=i&-i) c[i]+=y;
    }
     
    int ask(int x)
    {
        int ans=0;
        for(int i=x;i;i-=i&-i) ans+=c[i];
        return ans;
    }
     
    struct vv
    {
        int l,r,c;
    } s[M],q[M];
     
    bool cmp(vv a,vv b)
    {
        return a.r<b.r;
    }
     
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&s[i].l,&s[i].r,&s[i].c);
            C=max(C,s[i].r);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].c=i;
        }
        sort(s+1,s+1+n,cmp);
        sort(q+1,q+1+m,cmp);
        int l=1;
        for(int i=1;i<=m;i++)
        {
            while(s[l].r<=q[i].r && l<=n)
            {
                if(b[s[l].c]<s[l].l+1)
                {
                    if(!b[s[l].c]) cnt++;
                    if(b[s[l].c]) add(b[s[l].c],-1);
                    add(s[l].l+1,1);
                    b[s[l].c]=s[l].l+1;
                }
                l++;
            }
            res[q[i].c]=cnt-ask(q[i].l);
        }
        for(int i=1;i<=m;i++) printf("%d
    ",res[i]);
    }
     
     
     
  • 相关阅读:
    React Native For Android 环境搭建
    MySql 打开日志文件
    PHP使用JSON通信
    PHPStorm 调式JS /同时调式PHP和jS
    PHP list,explode的使用
    PHP foreach使用
    PHP eof的使用
    使用Spring缓存的简单Demo
    android源码的目录结构
    在Ubuntu上安装LAMP服务器
  • 原文地址:https://www.cnblogs.com/hua-dong/p/11385884.html
Copyright © 2020-2023  润新知