codeforces 862E Mahmoud and Ehab and the function 二分+思维

来源:互联网 发布:网络摄像机球机 编辑:程序博客网 时间:2024/06/05 21:10

传送门

题意:
给你序列a元素个数为n。b序列元素个数位m.对于每个j有:

给你q次修改,每次修改a数组的al,....ar。输出每次修改后最小的f(j)是?

思路:

可以观察到无论j怎么变化对于a数组的元素都是奇数为加,偶数为减.这个的和我们是可以提前维护好的,修改的时候由于整个区间(l,r)都增加x,所以只需要统计区间长度奇偶性就可以了.(要么只增加一个要么不增加).

然后我们观察b数组,发现b数组最多也是n个元素,并且j最大为m-n.所以我们可以预处理j为0,1,2,3,…m-n的所有的和,存起来然后二分一下求最小值即可.(因为是套绝对值所以值越接近越好).
怎么样预处理呢?可以想到对于每个不同j对应只是b数组中的起点不同,这个过程可以类似尺取一样,初始当j为0,第i个数,若i为奇数为+否则-. j每增加1,要把第一个元素的值减掉,然后正好全部变号了,这个过程每次乘以个-1即可.新加进来的数因为是第n个就取决于n的奇偶性了。

#include<bits/stdc++.h>#define pb push_backusing namespace std;typedef long long ll;const int maxn = 1e5+5;ll a[maxn],b[maxn];vector<ll>vt;int main(){    ll n,m,q;    while(cin>>n>>m>>q)    {        ll suma = 0;        ll sumb = 0;        vt.clear();        vt.pb(-1e18),vt.pb(1e18);        for(int i = 1;i <= n;++i)        {         scanf("%lld",&a[i]);         if(i & 1) suma += a[i];         else suma -= a[i];        }        for(int i = 1;i <= m;++i)        scanf("%lld",&b[i]);        for(int i = 1;i <= n;++i)        if(i & 1) sumb += b[i];        else sumb -= b[i];        vt.pb(sumb);        for(int i = n+1;i <= m;++i)        {            sumb -= b[i-n];            sumb *= -1;            if(n & 1) sumb += b[i];            else sumb -= b[i];            vt.pb(sumb);        }        sort(vt.begin(),vt.end());        int t=lower_bound(vt.begin(),vt.end(),suma)-vt.begin();        printf("%lld\n",min(abs(suma-vt[t]),abs(suma-vt[t-1])));        while(q--)        {            int l,r;            ll x;            scanf("%d%d%lld",&l,&r,&x);            if((r-l+1)&1)            {                if(l&1)suma += x;                else suma -= x;            }            t=lower_bound(vt.begin(),vt.end(),suma)-vt.begin();            printf("%lld\n",min(abs(suma-vt[t]),abs(suma-vt[t-1])));        }       }    return 0; } 
阅读全文
0 0
原创粉丝点击