Codeforces Round #673 (Div. 2) AE problem solution

Codeforces Round #673 (Div. 2) AE problem solution

Contest link: https://codeforces.com/contest/1417

Question A
Water, greedy

The question means that given a sequence of length n, and given an upper limit k, each number in the original sequence is between 1 and k, now you can add a certain number in the current sequence every time you operate To another number, but you can't let the value exceed k, now ask how many times you can operate at most.

Directly choose the one with the smallest value, and add as many other numbers as possible with this smallest value.

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n,k;
        cin>>n>>k;
        int ans=0,tar=0;
        vector<int>num(n);
        for(int i=0;i<n;i++)
        {
    
    
            cin>>num[i];
            if(num[i]<num[tar]) tar=i;
        }
        for(int i=0;i<n;i++)
            if(i!=tar) ans+=(k-num[i])/num[tar];
        cout<<ans<<endl;
    }
} 

Question B
Greedy, structure

The question means that given a sequence of length n, and given a value T, now you are required to divide the original sequence into two sequence, the two sequence of numbers in the same sequence of numbers that add up to T have the least number of subscripts.

Just be greedy. Put the half of T into the first series, and the half larger than T into the second series. The half of T can be divided evenly into less than two series. Because the half less than T can only be added to the half greater than T to be equal to T, you can simply divide them into two parts. The conclusion that is exactly equal to half of the uniform distribution can be calculated on the manuscript paper.

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        ll n,T;
        cin>>n>>T;
        bool flag=0;
        vector<bool>color(n);
        for(int i=0;i<n;i++)
        {
    
    
            ll x;
            cin>>x;
            if(x*2==T) {
    
    color[i]=flag;flag=!flag;}
            else if(x*2<T) color[i]=0;
            else color[i]=1;
        }
        for(int i=0;i<n;i++) cout<<color[i]<<' ';
        cout<<endl;
    }
}

C problem
string, small conclusion, simple use of map

Given a sequence of length n, you need to output the pair and the value of k with the value 1-n, the pair and all the continuous subsequences of length k in the sequence, and the smallest number in common. If there is no shared number, -1 is output.

If you think directly from the front, you will find it difficult to think. We can see from a specific value, if this value is used as the smallest common value of a certain length k, the length k needs to be no less than the maximum distance between adjacent positions in all the positions where the value appears in the sequence (note that The leftmost and rightmost side of the sequence shall be specially judged). Using this conclusion, we can use map to get the minimum k corresponding to each value in a for loop. After recording, directly perform 1-n on kfor as the answer, and output the minimum k.

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n;
        cin>>n;
        map<int,pair<int,int>>M;//M[i]=pair{j,k},代表值为i的数字最后出现在下标j的位置,值为i的数字之间的最大间隔为k
        for(int i=1;i<=n;i++)
        {
    
    
            int x;
            cin>>x;
            if(M.find(x)==M.end()) M[x]=make_pair(i,i);//数列左侧特判
            else
            {
    
    
                M[x].second=max(M[x].second,i-M[x].first);
                M[x].first=i;
            }
        }
        vector<int>ans(n+1,INF);
        for(auto &x:M)
        {
    
    
            x.second.second=max(x.second.second,n+1-x.second.first);//特判数列右侧
            ans[x.second.second]=min(ans[x.second.second],x.first);
        }
        int now=INF;
        for(int i=1;i<=n;i++)
        {
    
    
            now=min(now,ans[i]);
            if(now==INF) cout<<-1<<' ';
            else cout<<now<<' ';
        }
        cout<<endl;
    }
}

Question D
structure, thinking

The question means that given a sequence of length n, the value of each number is a positive integer between 1 and 1e5, and now you need to make the value of each number in this sequence at most 3n operations equal.
For each operation, you can choose two subscripts i and j, and choose a natural number x between 0 and 1e9, and subtract i × \times from ai× x, add i× \timesto aj× x。

First of all, notice that the sum of the entire sequence has not been changed during the operation, so first of all, the sum of the entire sequence must be constructed by an integer of the sequence length n. Then we noticed that the particularity of the operation here is that we need to multiply the subscript i for the value of the two subscripts. It is easy to think that if the number of subscript 1 is large enough, it can satisfy us in one operation. For the construction of a position, can we first gather all the values ​​of the entire sequence into a1 in some way, and then for all the positions allocated by n? We noticed that if we want to move all the values ​​at the position of aj to a1, the value of aj needs to be divisible by j. If the value of aj cannot divide j, we need to add the value to aj from elsewhere.
It is very easy to think of using a1 to add to aj to make aj divide j, and then we will find that...Directly for from 2 to n must complete the operation of clearing a2 to an, because every number in the original sequence It is a positive integer, which means that the sum of the previous n numbers is at least n, which means that the value of aj must be divisible by j.
So our first pass for subscripts 2 to n, each cycle of two operations, the first operation adds the value of a1 to aj so that aj can be divisible by j, and the second operation moves all the values ​​of aj to a1 on.
Such a round of operation consumes 2n-2 times, all the values ​​of the entire sequence are moved to a1, and then for the subscripts from 2 to n again, and the value can be directly moved from a1 to the construction. A total of 3n-3 operations are consumed, and the structure must be completed.

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const ll maxn=1e4+7;

ll num[maxn];
ll n,sum;

int32_t main()
{
    
    
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
    
    
        sum=0;
        cin>>n;
        for(ll i=1;i<=n;i++) {
    
    cin>>num[i];sum+=num[i];}
        if(sum%n) cout<<-1<<endl;
        else
        {
    
    
            sum/=n;
            cout<<3*(n-1)<<endl;
            for(ll i=2;i<=n;i++)//第一遍for把除了num[1]外的所有值清零,移动到num[1]上
            {
    
    
                ll temp=i-num[i]%i;
                if(temp==i) temp=0;
                cout<<1<<' '<<i<<' '<<temp<<endl;
                num[1]-=temp;
                num[i]+=temp;
                cout<<i<<' '<<1<<' '<<num[i]/i<<endl;
                num[1]+=num[i];
            }
            for(ll i=2;i<=n;i++) cout<<1<<' '<<i<<' '<<sum<<endl;//第二遍for直接利用num[1]构造
        }
    }
}

E title
operation, dfs divide and conquer, conclusion

The question means that given a number sequence of length n that only contains natural numbers, you need to find a suitable value out, so that each value in the original number sequence is XORed to get a new number sequence, which is in reverse order. The number num is the smallest, and the smallest num and the corresponding out value are output.

Here we need to realize that assuming there is only a sequence of 0 and 1, we can record how many times 0 and 1 appear in the process of a for loop, ending with 0 and 1 to form the number of reverse pairs, according to the two values The size difference determines whether we use 0 or 1 to XOR them.
From then on,
we look from high to low. Depending on the value, the number sequence will be divided into several sets corresponding to the depth power of 2. For different sets, the number of pairs in reverse order between them is already in The previous layer number process can be obtained according to the calculation process in the above paragraph, and then there will be no impact between each set, because the subsequent impact will only affect the lower level and will not affect the relationship between the current sets.
After pushing here, just write a dfs divide and conquer.

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int n;
ll ans=0,out=0;//ans为最终的数列中逆序对的数量,out为对原数列中每个值进行异或的值

void dfs(vector<vector<ll>>now,int deep)//二维数组now记录数列在当前层数被分割成了几个部分,deep为当前算的是二进制第几位
{
    
    
    ll temp=1ll<<deep;
    ll cas0,cas1,sum0=0,sum1=0;//sum0和sum1分别记录当前二进制deep位上,以该位为0的值作为逆序对的右侧(也就是out在此位取0)的逆序对数量
    //和以该位为1的值作为逆序对的右侧(也就是out在此位取1,使得该位的所有数0和1转化)的逆序对数量
    vector<vector<ll>>next;//下一次dfs的二维数组
    vector<ll>next0,next1;//当前分割部分的vector中,二进制deep位为0和1的数字分别放入两个vector
    for(int i=0;i<now.size();i++)
    {
    
    
        cas0=cas1=0;
        for(int j=0;j<now[i].size();j++)
        {
    
    
            if(now[i][j]&temp) {
    
    sum1+=cas0;cas1++;next1.push_back(now[i][j]);}
            else {
    
    sum0+=cas1;cas0++;next0.push_back(now[i][j]);}
        }
        if(next0.size()) {
    
    next.push_back(next0);next0.clear();}//避免不需要的递归和空间浪费,如果next0和next1不为0才压入下次dfs的数组里
        if(next1.size()) {
    
    next.push_back(next1);next1.clear();}
    }
    if(sum0>sum1) {
    
    ans+=sum1;out+=temp;}//如果以该位为0的值作为逆序对右侧的逆序对数量大于以该位为1的值作为逆序对的右侧,代表out需要在该位取1
    else ans+=sum0;
    if(deep==0) return;
    dfs(next,deep-1);
}

int32_t main()
{
    
    
    IOS;
    cin>>n;
    vector<vector<ll>>num(1);
    num[0].resize(n);
    for(auto &x:num[0]) cin>>x;
    dfs(num,30);//dfs30层即可,1e9的最高位也不过2的30次
    cout<<ans<<' '<<out<<endl;
}

Guess you like

Origin blog.csdn.net/StandNotAlone/article/details/108913241