CodeForces541div2-B-Draw!(有详细推导)

版权声明:未经博主同意,不可转载 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;
}

猜你喜欢

转载自blog.csdn.net/pythonbanana/article/details/87901098