zoukankan      html  css  js  c++  java
  • 百斯特

    先上题目:

    10679 多少个1

    时间限制:1000MS  内存限制:65535K
    提交次数:288 通过次数:22

    题型: 编程题   语言: C++;C

     

    Description

        Acm比赛里面经常需要巧妙方法处理数据,如求给定数组的最大连续和就可用到前缀和。现在给出一个给定长度的且初始化为0的数组,
    然后对该数组的一系列区间做取反操作,最后询问数组中有多少个1。(取反操作:原来是0就变为1,是1就变为0)




    输入格式

        输入第一行是t表示case数。每个case的第一行是用空格隔开的正整数n和m(0<n<=10^18,0<=m<=100000)分别表示数组长度和总操作数,
    接下来有m行,每行包含两个整数a和b(a、b之间用空格隔开,表示将位置a和位置b之间(包含a和b)的所有位进行取反操作,0<=a,b<n)。每个case后紧接一空行。



    输出格式

       每个case第一行输出:“Case #i:”,i表示第几个Case(从1开始);第二行输出数组1的个数



     

    输入样例

    2
    2000000000 1
    0 1000000000
    
    1000 3
    0 999
    0 100
    100 100
    



     

    输出样例

    Case #1:
    1000000001
    Case #2:
    900
    

      首先是最简单的方法:读入所有的区间,然后将区间里面的所有值取反。这样做绝对超时。

      然后是深一层的方法:先对所有区间离散化,然后构造线段树,接着更新线段树的区间。思路上可行,没有用这种方法实现过,算了一下时间复杂度:

      ①排序+离散化 O(mlogm)

      ②建树 O(mlogm)

      ③更新区间 O(mlogm)

      ④最终求值O(mlogm)

      这是上界,感觉不会超,但是实现起来还是比较麻烦。

      然后说一下第三种方法:使用归一化思想,见过观察,我们可以发现更新一个区间[l,r]的操作等价于更新[l,+∞]然后再更新[r+1,+∞],所以我们可以先处理出所有的变换后的左区间,然后排一次序,从小到大排序,然后加减交替更新即可,因为更新奇数次为加,更新偶数次不变。总的时间复杂度为O(mlogm)

    上代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <utility>
     5 #include <vector>
     6 #include <algorithm>
     7 #define MAX 100002
     8 #define ll long long
     9 //#define lld I64d
    10 using namespace std;
    11 
    12 ll n,m;
    13 ll l,r;
    14 ll s[MAX<<1],tot;
    15 
    16 int main()
    17 {
    18     int t;
    19     //freopen("data.txt","r",stdin);
    20     //ios::sync_with_stdio(false);
    21     scanf("%d",&t);
    22     for(int z=1;z<=t;z++){
    23         tot=0;
    24         scanf("%lld %lld",&m,&n);
    25         for(int i=0;i<n;i++){
    26             scanf("%lld %lld",&l,&r);
    27             if(l>r) swap(l,r);
    28             s[tot++]=l;
    29             s[tot++]=r+1;
    30         }
    31         sort(s,s+tot);
    32         ll sum=0,f=1;
    33         for(int i=0;i<tot;i++){
    34             if(s[i]>m) break;
    35             if(f){
    36                 sum+=m-s[i]+1;
    37             }else{
    38                 sum-=m-s[i]+1;
    39             }
    40             f=f^1;
    41         }
    42         //cout<<"Case #"<<z<<":"<<endl<<sum<<endl;
    43         printf("Case #%d:
    %lld
    ",z,sum);
    44     }
    45     return 0;
    46 }
    10679
  • 相关阅读:
    POJ 3126 Prime Path
    POJ 2429 GCD & LCM Inverse
    POJ 2395 Out of Hay
    【Codeforces 105D】 Bag of mice
    【POJ 3071】 Football
    【POJ 2096】 Collecting Bugs
    【CQOI 2009】 余数之和
    【Codeforces 258E】 Devu and Flowers
    【SDOI 2010】 古代猪文
    【BZOJ 2982】 combination
  • 原文地址:https://www.cnblogs.com/sineatos/p/4223801.html
Copyright © 2011-2022 走看看