zoukankan      html  css  js  c++  java
  • UCF Local Programming Contest 2017 I题 Rotating Cards(贪心+树状数组)

    这道题首先我们要发现的一个性质是,不过从是从后面取上来,还是从前面放到后面,当我们把想要的数字输出之后,序列是不变的,不信可以试试

    这个是关键点,因此,我们只要考虑哪种情况小就取哪种情况就行了,不用考虑顺序问题。

    之后还有一个问题是,如果快速求取花费值,我们进一步发现,这里的求值,永远是一段一段求的,

    比如 3 5 1 4 2,当我们取1的话,要不是后面一段要不是前面一段,对于区间求和,自然想到树状数组。但是当我们取完1后,序列发生改变,也就是顺序变化了,不能按之前的区间求和

    变成 4 2 3 5,所以我们要进一步发现性质,存一个pos值表示上次删的是哪个数,之后把当前要删的数的原位置和他进行比较,进行判断。

    那么比完之后该怎么求呢,这就需要大家自己推了,也可以看我的代码理解,提示的一点是,我们可以想象,当前值的位置在之前被删的数的前面,那么当前值和他前面的数都要移到后面去

    之后可以自己画图思考一下如何计算到底要求的是哪段和

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<map>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define ull unsigned long long
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=1e5+10;
    struct node{
        ll a;
        int pos;
    }s[N];
    ll tr[N];
    int n;
    int lowbit(int x){
        return x&-x;
    }
    void add(int x,ll c){
        int i;
        for(i=x;i<=n;i+=lowbit(i)){
            tr[i]+=c;
        }
    }
    ll sum(int x){
        int i;
        ll res=0;
        for(i=x;i;i-=lowbit(i)){
            res+=tr[i];
        }
        return res;
    }
    bool cmp(node a,node b){
        return a.a<b.a;
    }
    int main(){
        int t;
        cin>>t;
        while(t--){
            cin>>n;
            int i;
            for(i=1;i<=n;i++){
                scanf("%lld",&s[i].a);
                s[i].pos=i;
                add(i,s[i].a);
            }
            ll res=0;
            sort(s+1,s+1+n,cmp);
            int pos=s[1].pos;
            res+=min(sum(s[1].pos-1),sum(n)-sum(s[1].pos-1));
            add(s[1].pos,-s[1].a);
            for(i=2;i<=n;i++){
                int tmp=s[i].pos;
                ll up;
                ll down;
                if(tmp<pos){
                    up=sum(tmp-1)+sum(n)-sum(pos-1);
                    down=sum(pos)-sum(tmp-1);
                }
                else{
                    up=sum(tmp-1)-sum(pos);
                    down=sum(n)-sum(tmp-1)+sum(pos);
                }
                res+=min(up,down);
                add(tmp,-s[i].a);
                pos=tmp;
            }
            cout<<res<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【scala】定义变量和函数
    【python】self用法详解
    【Hive】自定义函数
    【Java】抽象类和接口
    Linux中的wheel用户组是什么?
    CentOS6.9切换root用户su root输入正确密码后一直提示Incorrect password,如何解决?
    CentOS7.X中使用yum安装nginx的方法
    Win10提示“因为文件共享不安全,所以你不能连接到文件共享”如何处理
    vim编辑器-多行加注释与去注释
    CentOS7.4用yum安装并配置MySQL5.7
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12643021.html
Copyright © 2011-2022 走看看