防线/秦腾与教学评估
作者:互联网
# 题意
一维的防线,有n组防具
每组防具通过s、d、k来描述,
如果某个位置上防具的个数是偶数个这个防线就是没有破绽的,0也是偶数所以没有防具也是可以的,有奇数个位置有防具就是破绽,整条防线最多只有一个位置上有破绽
t组测试数据,
防具的总数不超过1e8
0<= s、k、d <= 2^31-1
# 题解
1) 通过前缀和来使具有单调性,因为奇数最多只有一个,所以前缀和一定为奇数,即奇数+偶数为奇数
2) 具有了单调性就可以二分位置,当前前缀和为偶则左边一定全是偶,如果存在奇数的位置一定在右半区间
3) O(n)时间求出前缀和
设整个数列的最小位置为minidx
枚举每一个等差数列,设起点为s,终点为e,差为d,任意一点的x,如果s<=x则存在交集,则它与[minidx , x ]之间的共同区间为[s,min(e,x) ],则该区间中包含这个数列的个数为
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=2e5+10; 5 ll n; 6 struct node{ 7 ll s,e,d; 8 }a[N]; 9 inline ll check(ll mid){ 10 ll ans=0; 11 for(int i=1;i<=n;i++) 12 if(a[i].s<=mid) 13 ans+=(min(mid,a[i].e)-a[i].s)/a[i].d+1; 14 return ans; 15 } 16 int main(){ 17 ios::sync_with_stdio(0); 18 cin.tie(0); 19 cout.tie(0); 20 int t; 21 cin>>t; 22 while(t--) { 23 cin >> n; 24 for (int i = 1; i <= n; i++) 25 cin >> a[i].s >> a[i].e >> a[i].d; 26 ll l=0,r=1e9; 27 while(l<r){ 28 ll mid=l+r>>1; 29 if(check(mid)&1) 30 r=mid; 31 else 32 l=mid+1; 33 } 34 ll ans=check(r)-check(r-1); 35 if(ans&1) 36 cout<<l<<' '<<ans<<endl; 37 else 38 cout<<"There's no weakness."<<endl; 39 } 40 }
标签:防具,前缀,奇数,ll,防线,mid,秦腾,check,教学评估 来源: https://www.cnblogs.com/hhyx/p/12431129.html