K
看完题之后思路是很自然的:对于每个要求,就转化成对于l和r的限制。原本被题目解释干扰了,纠结了一下区间长度的限制觉得很复杂;后来发现只要l和r合法,区间长度就合法,所以对于1的限制直接取交,对于2的二选一的限制,直接按照l的限制排序,枚举l所在的区间,即可得到r的范围,再和一开始的交集取交即可。
这思路确实很容易也很好写,但写完疯狂wa2。。。还是有个小细节没注意到,,,有点破防
此处要和1取max,因为原本算出来的l可能小于0,原理其实和后面的和L取min是一样的,但1的限制太容易忽略(区间范围关系的计数题,应该把每个限制都写成区间的形式!!而不是只有一边的不等式),,,而且在上面其实考虑过限制1算出来<0的情况,也忘记考虑限制2了,只能说写题的时候脑子比较混乱
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int N=1e5+5,F=2e9+5;
int T,n,m,L,R;
struct node{
int l,r;
}p[N];
int mn[N];
bool cmp(node u,node v){
return u.l<v.l;
}
void work(int id){
cin>>n;
m=0;
L=F; R=1;
while(n--){
int t;
ll k,x;
scanf("%lld%lld%lld",&t,&k,&x);
ll s=k*(k-1)/2;
int l=(int)((x-s)/k),r=(int)((x+s-1)/k+1);
if(t==1) L=min(L,l),R=max(R,r);
else p[++m]=(node){l,r};
}
if(L<=0){
puts("0");
return;
}
if(L==F){
puts("-1");
return;
}
sort(p+1,p+m+1,cmp);
p[0]=(node){0,0};
p[m+1]=(node){F,F};
mn[m+1]=F;
for(int i=m;i;i--) mn[i]=min(p[i].r,mn[i+1]);
ll ans=0;
for(int i=0;i<=m;i++){
int a=max(1ll,p[i].l+1),b=min(L,p[i+1].l);
if(a>b || mn[i+1]<=R) continue;
if(b==F || mn[i+1]==F){
puts("-1");
return;
}
else ans+=1ll*(b-a+1)*(mn[i+1]-R);
}
cout<<ans<<endl;
}
signed main()
{
cin>>T;
for(int i=1;i<=T;i++) work(i);
return 0;
}