J 新英雄
现在设计师有一个问题:假设索亚现在站在一个友方小兵上,他前面有 n 个小兵排成笔直的一队,从近到远从 1 到 n 编号,起点位置的友方小兵视为第 0 个小兵。相邻两个小兵距离为 1。小兵分为我方小兵和敌方小兵。
一开始索亚的法力值为 0。索亚可以用"踏"向前或向后移动到一个友方的相邻小兵上;或者在有法力时,用"斩"向前或向后移动到一个任意的相邻小兵上。那么索亚到最后一个小兵最短需要多少时间?
输入格式:
输入第一行两个正整数 n,m(1≤n≤1e9 ,1≤m≤1e5 )。
接下来共 m 行,每行共三个正整数 t,l,r(1≤t≤2,1≤l,r≤n)。
对于每一行,当 t=1 时,代表第 l 个到第 r 个是友方小兵;当 t=2时,代表第 l 个到第 r个是敌方小兵。保证每个整点有且只有一个小兵。
输出格式
输出共一行,如果索亚无法移动到最后一个小兵,则输出"0/21/0"(不含双引号)。
否则包含一个正整数,表示需要的最短时间。
输入样例 1:
8 2
1 1 5
2 6 8
输出样例 1:
16
输入样例 2:
8 2
1 1 1
2 2 8
输出样例 2:
28
输入样例 3:
1 1
2 1 1
输出样例 3:
0/21/0
先合并一下区间然后注意爆int和取整问题即可
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N= 1e5+10;
typedef long long ll;
int n,m;
struct qj{
ll l,r;
int flag;
inline bool operator<(struct qj a){
return l<a.l;
}
}p[N],s[N];
int cnt;
int main(){
cin>>n>>m;
for(int i=0;i<m;i++)cin>>p[i].flag>>p[i].l>>p[i].r;
sort(p,p+m);
for(int i=0;i<m;i++)
{
int l=p[i].l,r=p[i].r;
int flag=p[i].flag;
int j=i+1;
while(j<m&&p[j].flag==flag){
r=p[j].r;
j++;
}
s[cnt++]={l,r,flag};
i=j-1;
}
if(s[0].flag==2){
puts("0/21/0");
return 0;
}
ll ans=0,fl=0;
for(int i=0;i<cnt;i++){
int l=s[i].l,r=s[i].r;
int flag=s[i].flag;
if(flag==1){
ans+=(r-l+1)*3ll;
fl+=(r-l+1);
}
else {
if(fl>=(r-l+1)){
ans+=(r-l+1);
fl-=(r-l+1);
}
else {
int u=(r-l+1-fl);
ll lj=ceil(u/2.0)*2ll;
ans+=lj*3ll;
fl+=lj;
fl-=(r-l+1);
ans+=(r-l+1);
}
}
}
ans-=fl/2*2;
cout<<ans<<endl;
}