• codeforces733-C. Epidemic in Monstropolis 贪心加链表


    题意

    现在有一个怪兽序列a[i],权值大的怪兽可以吃权值小的怪兽,吃完之后权值大的怪兽的权值会变成两者权值的和,相邻的怪兽才能吃

    吃完之后,位置合并,队列前移,从左到右重新编号,重复这一过程,

    然后给你一个怪兽序列b[i],问你a[i]怎么操作能变成b[i],如果能操作,输出操作序列,如果不能操作就输出NO

    难点一,划分序列,由于b[i]的概念类似于前缀和,一旦b[i]是确定的数,那么a[i]序列的划分就是唯一的,b[i]和a[i]的和相等

    b[i]序列实际上就是对序列a[i]的唯一划分

    难点二,如何判定由b[i]划分的小区间一定能全部合并?我们的办法是,找最容易满足的条件,如果你能养起来尽可能大的怪兽

    ,一旦它成为了最大值,那么这个小区间一定是可以合并的,这个贪心策略看起来是显然的(笑,所以我们每次尽量合成最大的怪兽

    如果这样都合并不了整个区间,那么这个区间一定是不可合并的,我表示不会严格数学证明

    难点三,如果用数组这个数据结构,我发现合并这个操作,我完全不知道怎么写,加上vis数组?哪个被合并就哪个记为被访问?

    那么我们每次要找到两个没有被访问且连续的元素然后合并权值,操作vis,也不是不行,我觉得这个写法太tm恶心了

    我选择用链表,权值用a[i]存,nxt[i]存储每个元素的下一跳,合并操作就变成了连跳操作,nxt[i]=nxt[nxt[i]],

    但是对于数序号来说,我们要另外写一个函数来O(n),获取该元素的rank,还好n比较小

    难点三、输出最终的答案序列

    我用了vector,和结构体存储了位置了操作字符,不是很简单,有机会去看看大神们是怎么写的

    难点四、考虑b[i]序列是否是合法序列,少考虑了两种,这个太致命了,一开始我是有想法的,后来忘了填坑了,以后觉得不放心的

    地方都要加一个注释才行,具体坑点详见代码

    难点五、注意合并操作的更新位置,要想记录当前操作,需要先记录再更新,更新后再记录就是错的了,不是我们想要的信息

    #include <cstdio>
    #include <vector>
    #define ll long long
    const int maxn=507;
    int n,k;
    int a[maxn],b[maxn],flag[maxn];
    int nxt[maxn];
    struct node{
        int pos;
        char type;
        //0 left 1 right
    };//结构体后面忘了加分号
    std::vector<node> ans;
    void init(int left,int right){
        register int i;
        for(i=left;i<right;++i){
            nxt[i]=i+1;
        }
        nxt[right]=-1;
    }
    bool check(int left,int right){
        if(nxt[left]!=-1) return false;
        return true;
    }
    int findIndex(int left,int index){
        int cnt=0;
        register int i;
        for(i=left;i!=-1;i=nxt[i]){
            cnt++;
            if(index==i){
                return cnt;
            }
        }
        return -1;
        //error
    }
    int solve(int left,int right,int pre){
            ll mx=-1;
            int index,first=1;
            register int i;
            for(i=left;i!=-1;i=nxt[i]){
                if(nxt[i]!=-1&&a[i]!=a[nxt[i]]){
                    if(first){
                        first=0;
                        mx=a[i]+a[nxt[i]];
                        index=i;
                    }
                    else{
                        ll temp=a[i]+a[nxt[i]];
                        if(temp>mx){
                            mx=temp;
                            index=i;
                        }
                    }
                }
            }
            if(mx!=-1){
                int pos1=findIndex(left,index);
                int pos2=findIndex(left,nxt[index]);
                if(a[index]>a[nxt[index]]){
                    ans.push_back((node){pre+pos1,'R'});
                }
                else{
                    ans.push_back((node){pre+pos2,'L'});
                }
                a[index]+=a[nxt[index]];//这两句话位置不对,之前做的早了
                nxt[index]=nxt[nxt[index]];
            }
            return mx;
    }
    int main(){
        scanf("%d",&n);
        register int i;
        ll suma=0,sumb=0;
        for(i=0;i<n;++i){
            scanf("%d",a+i);
            suma+=a[i];
        }
        scanf("%d",&k);
        for(i=0;i<k;++i){
            scanf("%d",b+i);
            sumb+=b[i];
        }
        if(suma!=sumb) {
            printf("NO
    ");
            return 0;
        }
        ll temp=0;
        int cur=0,cnt=0;
        for(i=0;i<n;++i){
            temp+=a[i];
            if(temp==b[cur]){
                flag[cnt++]=i;
                ++cur;
                temp=0;
            }
            else if(temp>b[cur]){
                printf("NO
    ");//NO 打成 No
                return 0;
            }
        }
        if(cur!=k) {
            printf("NO
    ");
            return 0;
        }
        register int j;
        int No=0;
        for(i=0;i<cnt;++i){
            int left,right=flag[i];
            if(i==0){
                left=0;
            }
            else{
                left=flag[i-1]+1;
            }
            init(left,right);
            while(!check(left,right)){
                int p=solve(left,right,i);
                if(p==-1){
                    No=1;
                    break;
                }
            }
            if(No){
                break;
            }
        }
        if(No) printf("NO
    ");
        else{
            printf("YES
    ");
            for(i=0;i<ans.size();++i){
                node t=ans[i];
                printf("%d %c
    ",t.pos,t.type);
            }
        }
        return 0;
    }
  • 相关阅读:
    增加Tomcat内存大小
    JAVA中的JSON
    js判断中文字符长度
    2016总结
    JavaScript 字符串实用常用操作
    Java文件操作
    hadoop中hbase出现的问题
    static_cast静态类型转换指针导致Release程序随机崩溃报错
    解决: error C2236: 意外的标记“class”。是否忘记了“;”?
    游戏操作杆代码
  • 原文地址:https://www.cnblogs.com/linkzijun/p/6063238.html
Copyright © 2020-2023  润新知