B. Light bulbs (2019上海网络赛)(差分)

题目连接

    题意:
            N 个 灯泡(编号 0 ~ N-1) M 次操作(初始灯都是关的)
            每次操作 给 2个数 L, R,把[L, R]区间内的开关翻转 
            求 M次操作后 有多少灯开着 
    
    数据范围 :  
                时间 1e9 
                T组样例  1e3
                N 1e6
                M 1e3
                0 <= L,R <= N -1    
    思路:     
            看到区间操作   区间更新 就想 线段树,和差分数组
            算下时间 每组样例 1e6
            1)线段树
            2)差分数组  
            3)直接差分后 还要有个O(N)遍历 所以 不可行,
            4)M很小,我们可以从M入手
            5)发现我们只需要考虑 2*M个有贡献的点就行了对与区间内的0 不需要遍历 
AC:

#include<iostream>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<stdio.h>
#include<map>
using namespace std;
const int maxn = 2e3 + 10;
int N, M;
pair<int, int> p[maxn];
int main() {
	int T, Case = 0;
	scanf("%d", &T);
	int Cnt = 0;
	while(T--) {
		Cnt = 0;
		scanf("%d%d", &N, &M);
		int L, R;
		for(int i = 1; i <= M; ++i) {
			scanf("%d%d", &L, &R); 
			p[Cnt++] = make_pair(L, 1);
			p[Cnt++] = make_pair(R + 1, -1); 
		}
		sort(p, p + Cnt);
		int Ans = 0;
		int Sum = 0;
		for(int i = 0; i < Cnt; ++i) {
			Sum += p[i].second;
			if(Sum & 1)//如果这个开关是开的  ,那到下个最近的灯泡操作前灯都是开的 
				Ans += p[i + 1].first - p[i].first;
		}
		printf("Case #%d: %d\n", ++Case, Ans);
	} 
	return 0;
}
发布了199 篇原创文章 · 获赞 156 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Harington/article/details/100879278