题目链接


题目大意:有n个灯,m次操作,每次修改[l,r]内的灯,(off - on ,on - off),问最后有几盏灯亮着.

题目思路:

因为外层有个T,并且n太大,并且卡内存!!!

我们只能对m下手,注意到:

把每一个端点存起来之后(并且排序),毎两个点之间的区间的 亮与否至于左边有关,不包括右边.

所以利用差分的思想,修改 L,R相当于a(L)+1,a(R+1)-1

我们把端点 排好序之后,就直接跑一遍m 

如果当前为左端点 则 覆盖层数++(意思就是 之后的每个数都多了一个区间覆盖)

如果当前为右端点 则覆盖层数--(意思就是 之后每个数都少了一个覆盖区间)

因为区间左闭右开,只要为奇数(灯亮),就加上左边右开区间 R-L的值

复杂度:(T*M):

#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;
}
/*
5
5 6
1 5
2 3
2 4
3 3
2 4
1 5
*
5 3
1 5
4 5
4 5
*/