Codeforces Round #673 (Div. 2) D 和 E

D

题意

给定一个长度为n为的数组,并且a[i] >= 1 每次可以选择两个数一个为 i,j  并选
则一个x给 a[i] -= x * i, a[j] += x * i 最终是所有的元素大小都相等,并且
每次操作完之后所有元素的大小都是非负的

题解

我们可以发现每次都是给整个数组加上一个数减去一个数,数组的总大小不变所以只有
当所有元素的和是n的倍数才能满足条件,至于操作我们可以客观的想因为只有第一个
数是我们可控(即他是所有数的约数),所有我们就可以先把所有的数都变为0,然后
在变为 sum / n把所有的数变为0  首先我们先使所有的数都变为i的倍数,我们就可以用 
第一个数来实现因为每个数都是大于1的,所以对于[2,n]按顺序做不会出现负数的情况,
最后在变为0 在变为sum / n 显然满足 3*n的条件

代码

#include
#include
using namespace std;
const int N = 1e4+10;
#define int long long
int a[N];
struct Node{
    int a,b,c;
};
 
signed main(){
    // ios::sync_with_stdio(false);
    // cin.tie(0);
    
    int T;
    cin>>T;
    while(T--){
        vector ans;
        int n;
        cin>>n;
        int s = 0; 
        for(int i = 1;i<=n;i++)
            cin>>a[i],s += a[i];
        if(s % n != 0){
            puts("-1");
            continue;
        }
        int t = s / n;
        for(int i = 2;i<=n;i++){
            if(a[i] % i){
                ans.push_back({1,i,i - a[i] % i});  // 变为i的倍数
                // printf("%lld %lld %lld\n",1,i,i - a[i] % i);
                a[i] += i - a[i] % i;  // 变为 0
            }
            ans.push_back({i,1,a[i]/i});
            // printf("%lld %lld %lld\n",i,1,a[i] / i);
        }
        for(int i = 2;i<=n;i++){
            ans.push_back({1,i,t});  // 变为sum / n
            // printf("%lld %lld %lld\n",1,i,t);
        }
        cout<

E

题意

给定一个长度为n的数组 a,确定一个最小的x,使 x异或上数组a之后的逆序对的
个数最少

题解

位运算一个很明显的性质,位运算可以指对一个位置产生影响,我们就可以分别处理
每一个位置,每个位置有0和1两种情况异或 0或1 都会产生不同的结果,
我们可以从最高位处理 ,每次处理前缀相同的二进制当前位置为0或1,对于异
或0或1不同的结果,然后相同的数据在下一位继续处理一直到第0位为止,中间的
关系可以使用图存储(因为最后是判断对所有的关系,而不是只是对这个局部的关系)。
最后我们就可以使用bfs每次搜索一位(bfs一次搜索一层),确定这为的x这一位选
择0或1进而能推出答案

代码

#include
#include
#include
#include
using namespace std;
#define int long long
const int N = 3e5+ 10,M = 1e7+10;  //所有点的个数很迷
int cnt;
int f[M][2];
vector h[M];  // 建图
int n;
 
int dfs(int u,vector &nums){
    cnt ++;  // 对于每个部分虚拟化的点
    int r0 = 0,r1 = 0;
    vector num0;  // 都为0 的部分
    vector num1;   // 都为1 的部分
    int v = cnt;
    for(auto x:nums){
        if(x >> u & 1){    // 当前为1  
            f[cnt][0] += r0;   // 异或0的逆序对 0最大
            r1++;
            num1.push_back(x);
        }
        else{             // 当前为0
            f[cnt][1] += r1;  // 异或1的逆序对 1 最大
            r0++;
            num0.push_back(x);
        }
    }
    if(u&&num0.size()) {
        int b = dfs(u - 1,num0);   // 处理下一层  该层都为1
        // add(v,b);
        h[v].push_back(b);
    }
    if(u&&num1.size()){
        int b = dfs(u - 1,num1);   // 处理下一层 该层都为0
        // add(v,b);?
        h[v].push_back(b);
    }
    return v;
}
signed main(){
    ios::sync_with_stdio(false);
    // memset(h,-1,sizeof h);
    cin>>n;
    vector nums;
    for(int i = 1;i<=n;i++){
        int x;
        cin>>x;
        nums.push_back(x);
    }
    int root = dfs(31,nums);   // 递归每一位
    int w = 31;
    queue q;
    q.push(root);
    int ans = 0;
    int res = 0;
    while(q.size()){     // bfs 判断每一位选择
        int r0 = 0,r1 = 0;
        int k = q.size();   // 所以的每一位的片段
        for(int i = 0;i

你可能感兴趣的:(#673,codeforces,div2,算法,dfs,数据结构)