zoukankan      html  css  js  c++  java
  • [AGC037C] Numbers on a Circle 题解

    直接加感觉不可做,于是考虑反过来,这样一次操作将 (B) 数组中一个数减去他左右数之和。

    即将 (B_i) 变为 (B_i-B_{i-1}-B_{i+1})

    首先 (A_i>B_i) 直接无解。
    再找切入点,相当于我们找转化后第一次操作,也就是原来的最后一次操作,由于每一个数必须是正整数,所以对于当前 (B) 数组中的最大值 (B_i)(B_{i-1})(B_{i+1}) 是不可以执行操作的,也就是说这两个数在对 (B_i) 执行操作前不能够改变。

    这样即使 (B_{i-1}) 需要操作,也必定在 (B_i) 之后(转化后的问题)操作。所以我们先对最大值操作,操作结束后,我们发现这个序列还可以继续按上面的方式找出最大值,于是再找最大值,这个过程可以用堆维护。

    • 每一步找出数组中最大值,对这个数执行操作直到不能再减为止。

    注意如果把一个数减到了 (A_i),就弹出可以数找剩下里面的最大值,相当于这个数永远不需要再操作了,移出这个体系。

    如果最大值已经没法再操作了,但是还是 ( eq A_i),就无解,因为能且只能影响它的左右位置的两个数一样没法变化。

    这样不能保证时间复杂度,所以需要把多次操作一起执行,我们直接每次减去直到不能再减为止,因为如果还可以再减,(B_i>B_{i-1}+B_{i+1})(B_{i-1})(B_{i+1}) 是还是不可以执行操作。

    这样一个数每次一定至少减半。

    时间复杂度 (O(nlog nlog W))(W) 为值域。

    using namespace std;
    typedef long long LL;
    
    LL n,ans = 0;
    LL a[200005],b[200005];
    LL c[200005];
    
    struct node{
        LL id,val;
        // 注意元素同时要存在数组中的位置
        bool operator < (const node &nd)const{
            return nd.val > val;
        }
    }h,t;
    priority_queue <node> q;
    
    bool cmp(LL x,LL y){
        return b[x] > b[y];
    }
    
    LL getnum(LL x){
        if(x == 0) return n;
        if(x == n + 1) return 1;
        return x;
        // 处理环问题
    }
    
    int main(){
        ios::sync_with_stdio(false);
        cin >> n;
        for(LL i = 1;i <= n;i ++) cin >> a[i];
        for(LL i = 1;i <= n;i ++) cin >> b[i];
        
        for(LL i = 1;i <= n;i ++){
        	if(a[i] > b[i]){
        		cout << -1 << endl;
        		return 0;
    		}
    	} // 无解
        
        for(LL i = 1;i <= n;i ++){
            if(a[i] < b[i]){
                t.id = i; t.val = b[i];
                q.push(t);
            }
        }
    
        while(!q.empty()){
            LL del,mns,i = q.top().id; q.pop();
            del = b[i] - a[i];
            mns = b[getnum(i - 1)] + b[getnum(i + 1)];
    
            if(del / mns == 0 && b[i] != a[i]){ cout << -1 << endl; return 0; }
            // 无解
    
            ans += del / mns;
            b[i] -= (del / mns) * mns;
            // 直接减完
            if(b[i] > a[i]){
                t.id = i; t.val = b[i];
                q.push(t);
            }
    		// 还没到 a[i],到了就不用再入队了
        }
        cout << ans << endl;
        return 0;
    }
    

    原评分 (sf{color{blue}1961})
    前置知识:堆
    代码难度/实现难度:很低吧

  • 相关阅读:
    Codeforces Round #650 (Div. 3)
    C. Count Triangles
    A National Pandemic (思维 + 树链剖分模版)
    扫描线专题
    扫描线模版
    莫队模版
    JS设计模式 -- 4种创建型模式
    滑动窗口的最大值 -- 单调队列
    JS链表实现栈和队列
    js数组扁平化的几种实现方式
  • 原文地址:https://www.cnblogs.com/IltzInstallBI/p/12744253.html
Copyright © 2011-2022 走看看