版权声明:未经博主同意,不可转载 https://blog.csdn.net/pythonbanana/article/details/87901098
题目传送门
题意:
题目转化为同一个选手的相邻比分构成一个闭区间(最开始的0 0也算),求这些区间的交集大小(不能重复计算,端点值注意不要计算)。
思路:
设a1 b1 a2 b2分别是上一次和当前的比分,我们计算区间[a1,a2],[b1,b2]的交集的时候,一般是min(a2,b2) - max(a1,b1) + 1(如果前者小于后者则continue).这样计算的话,我们将两个区间的所有点都就算在内了,那么之前的端点有没有在上次已经计算了呢?
如果a1 != b1,那么min(a1,b1) < max(a1,b1),在上一次计算的时候,使用min(a1,b1)计算的,所以min(a1,b1)这个端点会计算在内。在当前计算的时候,使用的是max(a1,b1),min(a2,b2) - max(a1,b1) + 1会把max(a1,b1)就算在内,但是由于min(a1,b1) < max(a1,b1),所以上次的min(a1,b1)在这一次没有重复计算。
如果a1 == b1,那么min(a1,b1) == max(a1,b1),在上一次计算的时候,使用min(a1,b1)计算的,所以min(a1,b1)这个端点会计算在内。在当前计算的时候,使用的是max(a1,b1),min(a2,b2) - max(a1,b1) + 1会把max(a1,b1)就算在内,但是由于min(a1,b1) == max(a1,b1),所以上次的min(a1,b1)在这一次重复计算。所以使用的是min(a2,b2) - max(a1,b1) 。
最后ans+1,加上最开始的0 0
下面的代码都是AC的。
详情见代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i = a;i <= b;++i)
#define rep(i,a,b) for(int i = a;i >= b;--i)
const int maxn = 1e4;
int n = 0,m = 0;
struct node{
int s,e;
};
node a[maxn+10];
void solve(){//思维能力还是不行,总想着细致模拟,把问题想得太复杂,太细节化,这就是大佬和弱鸡的区别
LL ans = 0;
per(i,1,n){
if(min(a[i].s,a[i].e) < max(a[i-1].s,a[i-1].e)){
continue;
}
if(a[i-1].s == a[i-1].e){//如果前面的比分相等,那么他在上一次计算就已经算过了,每一次都是[]闭区间,
//如果不相等,那么上一次用的是min(a[i-1].s,a[i-1].e),而这一次使用的是max(a[i-1].s,a[i-1].e)
//因为a[i-1].s != a[i-1].e,所以两者不相等,所以断电不会重复算
ans += (min(a[i].s,a[i].e) - max(a[i-1].s,a[i-1].e));
}else{
ans += (min(a[i].s,a[i].e) - max(a[i-1].s,a[i-1].e) + 1);
}
}
printf("%I64d\n",ans+1);//最后+1,加上0 0
}
int main(){
//std::ios::sync_with_stdio(false);
while(~scanf("%d",&n)){
a[0].s = a[0].e = 0;
per(i,1,n){
scanf("%d %d",&a[i].s,&a[i].e);
}
solve();
}
return 0;
}
比赛的时候想得复杂版本:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i = a;i <= b;++i)
#define rep(i,a,b) for(int i = a;i >= b;--i)
const int maxn = 3e5;
int n = 0,m = 0;
struct node{
int s,e;
};
node a[maxn+10];
void solve(){
LL ans = 0;
bool flag = false;
per(i,1,n){
if(a[i].s == a[i-1].s && a[i].s == a[i].e && a[i].s == a[i-1].e){
if(i >= 2 && a[i].s == a[i-2].s || flag == true){
continue;
}
++ans;
flag = true;
continue;
}
if(a[i].s < a[i-1].e || a[i].e < a[i-1].s){
continue;
}
int l = max(a[i-1].s,a[i-1].e);
int r = 0;
if(a[i].s == a[i].e){
r = min(a[i].s,a[i].e);
ans += max(0,r - l);
if(flag == false){
++ans;
flag = true;
}
continue;
}else if(a[i].s > a[i].e){
r = min(a[i].s-1,a[i].e);
}else{
r = min(a[i].s,a[i].e-1);
}
if(flag == false){
++ans;
}
ans += max(0,r - l);
flag = false;
}
printf("%I64d\n",ans);
}
int main(){
while(~scanf("%d",&n)){
a[0].s = a[0].e = 0;
per(i,1,n){
scanf("%d %d",&a[i].s,&a[i].e);
}
solve();
}
return 0;
}