题意:
N 个 灯泡(编号 0 ~ N-1) M 次操作(初始灯都是关的)
每次操作 给 2个数 L, R,把[L, R]区间内的开关翻转
求 M次操作后 有多少灯开着
题解:
暴力 O(NT) 复杂度到达1e9 TLE
线段树 树状数组 O(TN*logn)也会超时
这个题内存也很小,对M次操作进行处理。
先对m组数据存下来,按照从小到大排序。
差分数组
p【l】=1 p【r+1】=-1 理解为我们把 L 右边的所有灯全部转化,区间为L,R 所以我们还的把R+1 右边全部转化。
对着m*2个排好的数据进行操作,从最小的开始,用sum表示这个数到下一个数是奇数还是偶数,奇数的话变化了奇数次 ,就说明这个数到下个数变化了奇数次,这个数到下个数灯都是开着的,加上灯的个数 。变化偶数次都是关的。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
ll index,num;
}p[5000];
ll cmp(node a,node b)
{
return a.index<b.index;
}
int main()
{
ll t,k=1;
scanf("%lld",&t);
while(t--)
{
ll n,m,cnt=0;
scanf("%lld%lld",&n,&m);
for(int i=0;i<m;i++)
{
ll l,r;
scanf("%lld%lld",&l,&r);
p[cnt].index=l;
p[cnt++].num=1;
p[cnt].index=r+1;
p[cnt++].num=-1;
}
sort(p,p+cnt,cmp);
ll sum=0,ans=0;
for(int i=0;i<cnt;i++)
{
sum+=p[i].num;
if(sum&1)
ans+=p[i+1].index-p[i].index;
}
printf("Case #%lld: %lld\n",k++,ans);
}
return 0;
}