您的位置:首页 > 其它

10679 多少个1

2014-03-18 10:41 351 查看

10679多少个1

该题有题解

时间限制:1000MS内存限制:65535K

题型:编程题语言:无限制

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
20000000001
01000000000

10003
0999
0100
100100

输出样例

Case#1:
1000000001
Case#2:
900

一开始看这道题一点思路都没有,后来学了线段树,回想起这道题似乎可以用线段树做,由于数据很大10^18,所以考虑离散化,可是发现了新问题:
比如:103
15
710
55
77
对于这种情况始终解决不了,于是就。。。。。。(没有了)
上面的题解是对于区间[a,b]取反相当于对[a,+∞)取反后再对[b+1,+∞)取反;

实现代码

[code]#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
usingnamespacestd;
typedeflonglongll;
constintM=100010;
inta[M<<1],cas=1;

voidsolve(){
lln,m;
scanf("%lld%lld",&n,&m);

intk=0,i=0;
for(;i<m;i++){
llx,y;
scanf("%lld%lld",&x,&y);
if(x>y)swap(x,y);
a[k++]=x,a[k++]=y+1;
}

printf("Case#%d:\n",cas++);
sort(a,a+k);

llans=0;
for(i=1;i<k;i+=2)ans+=a[i]-a[i-1];

printf("%lld\n",ans);
}

intmain(){
intT;
scanf("%d",&T);
while(T--)solve();
return0;
}

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
章节导航