题目链接:https://nanti.jisuanke.com/t/41399
题目大意:有n个灯,m次操作,每次修改[l,r]内的灯,(off - on ,on - off),问最后有几盏灯亮着.
用一般的暴力思路会超时
把每一个端点存起来之后(并且排序),毎两个点之间的区间的 亮与否至于左边有关,不包括右边.
所以利用差分的思想,修改 L,R相当于a(L)+1,a(R+1)-1
我们把端点 排好序之后,就直接跑一遍m
如果当前为左端点 则 覆盖层数++(意思就是 之后的每个数都多了一个区间覆盖)
如果当前为右端点 则覆盖层数--(意思就是 之后每个数都少了一个覆盖区间)
因为区间左闭右开,只要为奇数(灯亮),就加上左边右开区间 R-L的值
#include<algorithm>
#include <string.h>
#include<stdio.h>
#define ll long long
using namespace std;
const int maxn=1e6+7;
const ll INF=1e9;
ll n,m;
struct node{
int f=0;
ll id;
bool friend operator<(node a,node b)
{
if(a.id==b.id) return a.f<b.f;
return a.id<b.id;
}
}pos[2005];
int main()
{
int t;
int cas=0;
scanf("%d",&t);
int cnt=0;
while(t--)
{
ll cnt=0,ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
pos[++cnt].id=x;pos[cnt].f=0;
pos[++cnt].id=y+1;pos[cnt].f=1;
}
int cot=0;
sort(pos+1,pos+1+cnt);
for(int i=1;i<=cnt-1;i++)
{
if(pos[i].f) cot--;
else cot++;
if(cot%2) ans+=pos[i+1].id-pos[i].id;
}
printf("Case #%d: %lld\n",++cas,ans);
}
return 0;
}