其他分享
首页 > 其他分享> > 防线/秦腾与教学评估

防线/秦腾与教学评估

作者:互联网

# 题意
一维的防线,有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