zoukankan      html  css  js  c++  java
  • 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
    ");
            else printf("%d
    ",cnt);
        }
    }
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    大型网站核心架构因素
    大型网站架构模式
    博客中的文章归档是如何实现的
    Caused by: java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
    git分支开发的好处
    layui之日期和时间组件
    vue-electron脚手架
    springboot1.5.4 配置druid1.1.0(使用druid-spring-boot-starter)
    Node.js读取文件内容并返回值(非异步)
    C# ftp ListFilesOnServer
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/9691097.html
Copyright © 2011-2022 走看看