zoukankan      html  css  js  c++  java
  • P2184 贪婪大陆

    P2184 贪婪大陆

    传送门:https://www.luogu.com.cn/problem/P2184

    题目背景

    面对蚂蚁们的疯狂进攻,小FF的Tower defence宣告失败……人类被蚂蚁们逼到了Greed Island上的一个海湾。现在,小FF的后方是一望无际的大海, 前方是变异了的超级蚂蚁。 小FF还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造SCV布置地雷以阻挡蚂蚁们的进攻。

    题目描述

    小FF最后一道防线是一条长度为N的战壕, 小FF拥有无数多种地雷,而SCV每次可以在[ L , R ]区间埋放同一种不同于之前已经埋放的地雷。 由于情况已经十万火急,小FF在某些时候可能会询问你在[ L' , R'] 区间内有多少种不同的地雷, 他希望你能尽快的给予答复。

    对于30%的数据: 0<=n, m<=1000;

    对于100%的数据: 0<=n, m<=10^5.

    输入格式

    第一行为两个整数n和m; n表示防线长度, m表示SCV布雷次数及小FF询问的次数总和。

    接下来有m行, 每行三个整数Q,L , R; 若Q=1 则表示SCV在[ L , R ]这段区间布上一种地雷, 若Q=2则表示小FF询问当前[ L , R ]区间总共有多少种地雷。

    输出格式

    对于小FF的每次询问,输出一个答案(单独一行),表示当前区间地雷总数。

    输入输出样例

    输入 #1
    5 4
    1 1 3
    2 2 5
    1 2 4
    2 3 5
    
    输出 #1
    1
    2


    简而言之就是,q==1时,给l到r染上一种颜色,q==2时,询问l到r内一共有多少种颜色呐,在线区间修改,我们想到了线段树,线段树这个题是绝对可以做的,那线段树用来维护什么呢

    因为要统计的是一段区间内有多少段曾经出现过的区间,我暂时的想法是在树上分别维护左端点出现的次数,右端点出现但的次数,还得知道左端点就能找到右端点的这么一组关系

    然后查询的时候查区间内左端点和右端点的和-左右端点都在这个区间的数量(对于每一个左端点查询右端点是否在区间内)

    不过为什么是暂时的呢,讲真,这太麻烦了,都给我想睡着了所以咱们换一种方法

       只要一个区间的开头在一个节点i的左边,那么这个区间包含在区间1~i中

       只要一个区间的尾部在一个节点j的左边,那么这个区间肯定不属于j之后的所有区间

       所以我们只需要维护区间的开头和结尾的位置,查询时查找r之前有多少个开头-l之前有多少个结尾,就可以了

       因为线段树还是有一些繁琐(码量多)

       这个问题用树状数组就可以做辣

    sum1 开头位置
    sum2 结尾位置

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define lowbit(a) ((a)&-(a))
     5 #define clean(a,b) memset(a,b,sizeof(a))
     6 const int mod = 1e9 + 7;
     7 const int inf=0x3f3f3f3f;
     8 const int maxn = 2e5+9;
     9 
    10 inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
    11 int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
    12 
    13 int _;
    14 //////////////////////////////////////////////////////////////////////////
    15 ll sum1[maxn],sum2[maxn];
    16 void update(int x,ll y,int n,ll *c)///One point update
    17 {
    18     for(int i=x; i<=n; i+=lowbit(i))
    19         c[i] += y;
    20 }
    21 ll get_sum(int x,ll *c)///Interval query
    22 {
    23     ll ans = 0;
    24     for(int i=x; i; i-=lowbit(i))
    25         ans += c[i];
    26     return ans;
    27 }
    28 //////////////////////////////////////////////////////////////////////////
    29 int main()
    30 {
    31     int n=read();
    32     int m=read();
    33     for(int i=1;i<=m;i++) 
    34     {
    35         int q=read();
    36         if(q==1)
    37         {
    38             int l=read();
    39             int r=read();
    40             update(l,1,n,sum1);
    41             update(r,1,n,sum2);
    42         }
    43         else 
    44         {
    45             // for(int i=1;i<=10;i++) printf("%lld %lld
    ",sum1[i],sum2[i]);
    46             int l=read();
    47             int r=read();
    48             ll ans=get_sum(r,sum1)-get_sum(l-1,sum2);
    49             printf("%lld
    ",ans);
    50         }
    51     }
    52     return 0;
    53 }


  • 相关阅读:
    Java基础面试题18--单例设计模式
    Error:The method setInputPaths(JobConf, String) in the type FileInputFormat is not
    java基础面试题17--类的加载、对象的加载流程
    隐私策略-en
    隐私策略-ch
    Java 11 相关
    kali BugFix
    bugFix
    xcode 快捷键
    QT 静态编译 windows&mac 版本
  • 原文地址:https://www.cnblogs.com/YangKun-/p/12870531.html
Copyright © 2011-2022 走看看