ACM/ICPC 2018亚洲区预选赛北京赛站网络赛D-80 Days--------树状数组

 题意就是说1-N个城市为一个环,最开始你手里有C块钱,问从1->N这些城市中,选择任意一个,然后按照顺序绕环一圈,进入每个城市会有a[i]元钱,出来每个城市会有b[i]个城市,问是否能保证经过每个城市,钱都不会能为0,如果可以请输出最小的那个   

这题最开始队员想错了。。。后来思路就乱了,整理一下思路,你会发现,其实我们要求的就是从i到n+i的前缀和最小值一定要大于c。 

那么如何解决这个问题呢???

你会发现,其实我们只需要算一个影响就行,假如最小的点的在ID,那么前面i->ID的数肯定小,对吧???

如果ID<0,我从i到id,依次减去这个点的贡献,直到ID>=0,那么由于i到ID,ID到N这些数肯定是比ID大的,因此我们只需要看尾部增加的值的是否小于0并且是否小于最小值,如果小于我们,把最小值和最小值的位置更新,这样我们就实现了区间的移动,这样不断移动,我们判断移动是否超过N,如果超过N,证明找不到这个点,如果可以,直接break,输出就可以了。

个人感觉有点莫队的意思。。。

#include<bits/stdc++.h>
using namespace std;

int t;
typedef long long ll;
const int maxn = 1e6+5;

struct Node
{
    ll a,b,w;
} node[maxn<<1];

int n,c;
ll tree[maxn<<1];

int lowbit(int x)
{
    return x&(-x);
}

void add(int x,ll v)
{
    for(int i=x; i<=n; i+=lowbit(i))
    {
        tree[i] += v;
    }
}

ll query(int x)
{
    ll ans = 0;
    for(int i=x; i>0; i-=lowbit(i))
    {
        ans += tree[i];
    }
    return ans;
}

int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&c);
        memset(tree,0,sizeof(tree));
        for(int i=1; i<=n; i++)
            scanf("%lld",&node[i].a);
        ll minn = 0x3f3f3f3f3f;
        int id = 0;
        ll tmp = c;
        for(int i=1; i<=n; i++)
        {     
            scanf("%lld",&node[i].b);
            node[i].w = node[i].a - node[i].b;
            node[i+n].w = node[i].w;
            add(i,node[i].w);
            add(i+n,node[i].w);
            tmp += node[i].w;
            if(tmp < minn)
            {
                minn = tmp;
                id = i;
            }
        }
        int cnt = 1;
        int len = id;
        while(minn < 0)
        {
            if(cnt > n)break;
            for(int i=cnt;i<=cnt + len - 1;i++)
            {
                minn -= node[i].w;
                if(minn >= 0)
                {
                    cnt = i+1;
                    break;
                }
            }
            ll tmp = query(n) - query(cnt-1) + c;
            minn = 0;
            for(int i=n+1;i<=n+cnt-1;i++)
            {
                tmp += node[i].w;
                if(tmp < 0)
                {
                    if(tmp < minn)
                    {
                        minn = tmp;
                        id = i;
                    }
                }
            }
            len = id - cnt + 1;
        }
        if(cnt > n)printf("-1\n");
        else printf("%d\n",cnt);
    }
}

 

posted @ 2018-09-22 20:35  bluefly-hrbust  阅读(485)  评论(0编辑  收藏  举报