题意:
T组案例
每组案例:
n个灯泡,m次操作
每次操作把区间(L,R)内的灯泡翻转(开变关,关变开)
问m次操作之后有多少灯泡是亮着的
数据范围:
T<=1e3
n<=1e6
m<=1e3
时限1s,内存8000k
分析:
空间小时间少恶心人
差分每组O(n)都tle
但是因为m小,所以考虑从m入手
比赛的时候一手离散化+差分过了(600+ms)
但是刚刚看到别人的代码发现比自己的好很多(300+ms,不是离散化)
学习记录一下
下面挂两种代码:
code:
别人那边学到的
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
int read(){
int x=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x;
}
using namespace std;
const int maxm=1e3+5;
struct Node{
int id,f;
}q[maxm<<2];
bool cmp(Node a,Node b){
return a.id<b.id;
}
signed main(){
int T=read();
int cas=1;
while(T--){
int n=read(),m=read();
int cnt=0;
for(int i=1;i<=m;i++){
int l=read(),r=read();
q[++cnt].id=l;q[cnt].f=1;//差分左端点
q[++cnt].id=r+1;q[cnt].f=-1;//差分右端点
}
sort(q+1,q+1+cnt,cmp);
int sum=0;
int ans=0;
for(int i=1;i<=cnt-1;i++){
sum+=q[i].f;
if(sum%2)ans+=q[i+1].id-q[i].id;
}
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}
code:
我的
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
int read(){
int x=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x;
}
using namespace std;
const int maxm=1e3+5;
struct Node{
int l,r;
}q[maxm];
int xx[maxm*4];
int mark[maxm*4];
signed main(){
int T;
scanf("%d",&T);
int cas=1;
while(T--){
int n=read(),m=read();
int num=0;
for(int i=1;i<=m;i++){
q[i].l=read();
q[i].r=read();
xx[++num]=q[i].l;
xx[++num]=q[i].l+1;
xx[++num]=q[i].r;
xx[++num]=q[i].r+1;
}
sort(xx+1,xx+num+1);
num=unique(xx+1,xx+1+num)-xx-1;
for(int i=1;i<=num;i++){
mark[i]=0;
}
for(int i=1;i<=m;i++){
q[i].l=lower_bound(xx+1,xx+1+num,q[i].l)-xx;
q[i].r=lower_bound(xx+1,xx+1+num,q[i].r)-xx;
mark[q[i].l]++;
mark[q[i].r+1]--;
}
int ans=0;
int sum=0;
for(int i=1;i<=num;i++){
sum+=mark[i];
if(sum%2)ans+=xx[i+1]-xx[i];
}
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}