Codeforces Round #664 (Div. 2&&Div. 1) Div2 AE problem solution

Codeforces Round #664 (Div. 2&&Div. 1) Div2’s AE solution
// written in the large rating value of 2075/2184, and the small rating value of 1887/1887
//The first time to hit zero, and it was two after the game The questions are all dropped by the system
X.//Large div1 group, rating value -109
//Leaving school in these two days and going home at a relative’s house, there may be one or two pigeon races. Write supplementary questions after the game as usual

//There must be frustration, but it is true that I have a problem. Question A (corresponding to Div2's D) misunderstood the meaning of the question and a detail led to a code error, but the pretest can still be passed...B (corresponding to Div2's E ) The analysis of complexity is too poor, and it is true that my thinking is too narrow. I did not think about hashing at all. I thought it was a dfs pruning. I forcibly cut the pretest and retested the tle...
//I was educated, but also Let myself see the flaws, and now I really don't deserve the yellow name.
//Don't have to lose confidence or anything. The AC problem is still the "speed of light" as always. Compared with the 1300 dive of more than half a year ago, I have indeed improved a lot.
// Tomorrow will be better, ACMER has never been defeated by failures and setbacks

//After the game, fill up the AE question of div2 and write a solution as usual

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

Question A
Simple thinking

This question needs to grasp some essential characteristics, about parity

First, let's analyze the characteristics of a palindrome and the number of letters that make up the palindrome.
1. When the total length of the palindrome string is an even number, due to the letter at any position, there must be another letter at a different position in the palindrome string that is the same as it, so any letter appearing in this palindrome string , Its number of occurrences is even
. 2. When the total length of the palindrome string is even, the letter in the middle is a special position, which corresponds to itself, so its total number of occurrences is odd. That is to say, in this case, except for the letter in the middle position, all letters have an even number of occurrences, or to put it another way, there is only one letter with an odd occurrence.

In summary, under the condition that a palindrome can be formed, the number of occurrences of each letter in our hand is either all even numbers, or only one and only one is odd.

Looking at the current title again, we have four letters r, g, b, and w. We can count how many of these four occurrences are even, and record them as tot.

When tot is equal to 0 or 1, the conditions for forming a palindrome we introduced above have been met, and directly output Yes.
When tot is greater than 1, we need to judge whether tot can be changed to 0 by the operation method given in the title Or 1.

The operation given by the title is to turn 1 r, 1 g, and 1 b into 3 ws each time.
We noticed that the number of changes for the four letters is odd, which means that after each operation, the original number of occurrences will become even, and the original number of occurrences will become odd.

When tot is 2, that is, the odd number is 2 and the even number is 2. After the operation, the odd number is still 2, and the even number is still 2. Therefore
, when
No tot is 3, it is an odd number. The number is 3, the even number is 2, the odd number is 1 after the operation, and the even number is 3, which meets the requirements; when tot is 4, that is, the odd number is 4 and the even number is 0. After the operation The last odd number is 0, and the even number is 4, which meets the requirements. But at this time we need to check whether the number of the three letters of rgb is not 0, only in this way can we have the opportunity to operate. If it can be operated, output Yes, if it cannot be operated, output No. The
discussion is over

#include<bits/stdc++.h>
#define ll long long
#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 a,b,c,d;
        cin>>a>>b>>c>>d;
        int tot=0;
        if(a&1) tot++;
        if(b&1) tot++;
        if(c&1) tot++;
        if(d&1) tot++;
        if(tot==0||tot==1) cout<<"Yes"<<endl;
        else
        {
    
    
            if(tot>2&&a&&b&&c) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
    }
}

Question B
Simple structure

The title means that in a n × \times× m chessboard, at the beginning, a car was placed at the position (x, y) (the initial position must not be at the boundary position) (you can only walk horizontally or vertically), and now I hope you can output a walking path. Go through every point on the board. (Note that every time you move, only the end point is taken as the one you walked to, the point in the middle of the road is not counted)

First think of a plan that starts at (1,1), which is the upper left corner, that can walk through the entire chessboard. At first, go to the right, then go down 1 square after you reach the head, then go left, and then go down 1 square after the head. Go back to the right... keep looping, which is a serpentine route.

Then we first move the chess piece up from the initial position (x, y) to the position (1, y) and then to (1, 1), and then follow the above-mentioned route to meet (1, y) and ( x, y) The two grids go past them. Since the initial position is not on the boundary, that is to say, y is not equal to 1 nor m, it is definitely feasible for us to skip these two positions. (Be careful not to move to the left to (x, 1) in the first step. The left and right boundary positions are the points where we change the walking direction under our scheme, which will make our path difficult to construct.)
Then the code simulation completes this process.

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

int32_t main()
{
    
    
    IOS;
    int n,m,x,y;
    cin>>n>>m>>x>>y;
    cout<<x<<' '<<y<<endl;//初始位置
    cout<<1<<' '<<y<<endl;//移动到最上面
    for(int i=1;i<=n;i++)//从(1,1)向右,开始走蛇形路线
    {
    
    
        if(i&1)//奇数行向右走
        {
    
    
            for(int j=1;j<=m;j++)
            {
    
    
                if(j==y&&(i==1||i==x)) continue;//碰到(1,y)和(x,y)这两个点就跳过
                cout<<i<<' '<<j<<endl;
            }
        }
        else//偶数行向左走
        {
    
    
            for(int j=m;j>=1;j--)
            {
    
    
                if(j==y&&(i==1||i==x)) continue;
                cout<<i<<' '<<j<<endl;
            }
        }
    }
}

C
positional operations, greedy, violence

The question means to give you two arrays a and b with lengths n and m respectively. For each number in array a, you need to find a number in array b and perform & operation with it as the value of c array . (For the numbers in different a arrays, you can select the numbers in the same b array to perform operations)
Now in the c array with length n you want to construct, all numbers get the smallest value after | This minimum value.

First of all, we have to summarize the characteristics of | (or) operation, or operation. For the same binary bit, the binary number corresponding to any number has 1 in that bit, then the final result must have 1 in this bit.
For the greedy strategy, for the highest 1, we must hope that it will be cleared out first.
We directly check the brute force for loop, in all a arrays, whether the current number is 1 in the highest position, and if it is 1, can the 1 be removed by & operation with the number in the b array. If all the numbers in the a array can be removed by the & operation, it means that the final result may not include the highest 0.
For the lower ones, if the previous higher bits have 1s that can be completely removed, then its selection must be made on the basis of those that can remove these highest bits. We use a del array to record which higher bits are 1 can be deleted all, in the process of violent for loop detection, just add one to check whether there is no 1 for every bit in the del array.

The final answer is the initial value with all 1 bits, that is, (1<<9)-1, minus the value after 1 on all the bits that can be removed in the del array.

In the question conditions, the number is up to 9 bits binary, and the complexity is O(9 × \times× 9 × \times × n × \times × m) The complexity of the 3e7 level is dead.

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

vector<int>del;//记录当前为止,哪些更高位的1可以被删除,对于更低位的1来说,在&运算删除自身位上1的过程中还需满足同时删除所有del中更高位的1

int32_t main()
{
    
    
    IOS;
    int n,m;
    cin>>n>>m;
    vector<int>a(n),b(m);
    for(auto &x:a) cin>>x;
    for(auto &x:b) cin>>x;
    for(int i=8;i>=0;i--)
    {
    
    
        int flag=1;//记录第i位的1是否可全部通过&运算除去
        for(int j=0;j<n;j++)
        {
    
    
            if(a[j]&(1<<i))//如果a[j]的第i位上出现了1,检测是否可以通过&运算将这个1除去
            {
    
    
                bool F=0;//记录a[j]&b[]是否存在一个组合满足不存在更高的已经确定可删除的位以及当前位上出现1
                for(int k=0;k<m;k++)
                {
    
    
                    int temp=a[j]&b[k];
                    bool f=1;//记录a[j]&b[k]的值是否满足不存在更高的已经确定可删除的位以及当前位上出现1
                    for(auto x:del) if(temp&(1<<x)) f=0;
                    if(temp&(1<<i)) f=0;
                    if(f) F=1;//出现任意一个满足要求的组合,F置为1
                }
                if(!F)
                {
    
    
                    flag=0;//如果任意一个a[]无法将第i位上的1除去,那么flag就为0
                    break;
                }
            }
        }
        if(flag) del.push_back(i);//如果所有第i位的1都可在满足删除更高位的必须删除的1的基础上,同时可删除第i位的1
        //代表第i位的1也可被除去,压入del数组中
    }
    int ans=(1<<9)-1;
    for(auto x:del) ans-=(1<<x);
    cout<<ans<<endl;
}

Question D
Greed, violence, prefix sum

Given n numbers, you need to find a permutation that has the largest sum in the end under the condition of meeting the requirements of the question.
The question requires that in the process of sweeping from the head to the end of the sequence, if a certain value is greater than the given value m, then the consecutive d numbers after this number will not be included in the final total.

//During the competition, when d=1, m=2,
the result of the sequence 3 3 4 is understood as 3
//but the actual result should be 7
//I don’t know how I cheated the pretest...

First of all, for all numbers greater than m, if we want to get a certain value, then the corresponding d numbers after him cannot be included in the final result. That is to say, for every d+1 number, we can get a number greater than m (of course this is not necessarily the optimal structure).
If we have x numbers in our hands, let x/(d+1) be cas. If x%(d+1) is equal to 0, then this x number can make cas numbers greater than m be selected at most, if x If %(d+1) is not 0, we can add another group at the end of the last part, so that at most cas+1 numbers greater than m can be selected.

For numbers less than or equal to m, as long as they do not appear in the d numbers after the number greater than m, they will inevitably be taken. We can enumerate how many numbers less than or equal to m are taken (of course these numbers It is the largest of the numbers less than or equal to m, placed at the front of the number sequence), and the remaining numbers are used as the construction of numbers greater than m, and the operations in the above paragraph are performed together with numbers greater than m. Those selected among the numbers greater than m are naturally the largest.

Therefore, we divide the numbers into two categories according to greater than m and less than or equal to m. After sorting from largest to smallest, we find a prefix sum, and then we can query O(1) what is the sum of the first i largest numbers. Violent enumeration is less than or equal to The number of m is the number we want to get.

Other discussion methods have more or less difficult to think about or can not be discussed at all. Only this method is the most concise. This idea actually appeared once in a question six months ago.

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

ll n,d,m;
deque<ll>high,low;

bool cmp(ll a,ll b)
{
    
    
    return a>b;
}

int32_t main()
{
    
    
    IOS;
    cin>>n>>d>>m;
    for(ll i=0;i<n;i++)
    {
    
    
        ll x;
        cin>>x;
        if(x>m) high.push_back(x);
        else low.push_back(x);
    }
    d++;
    sort(high.begin(),high.end(),cmp);
    sort(low.begin(),low.end(),cmp);
    high.push_front(0);
    low.push_front(0);
    ll ans=0;
    for(ll i=1;i<high.size();i++)
        high[i]+=high[i-1];
    for(ll i=1;i<low.size();i++)
        low[i]+=low[i-1];
    for(ll i=0;i<low.size();i++)//i为小于等于m的数字中我们取的个数
    {
    
    
        ll j=(n-i)/d;//j为大于m的数字中我们取的个数
        if((n-i)%d) j++;
        j=min((ll)high.size()-1,j);
        ans=max(ans,high[j]+low[i]);
    }
    cout<<ans<<endl;
}

Question E
Violent dfs, hash optimization detection

Once I see E, it shouldn’t be necessary to elaborate as above (I’m hungry and want to eat quickly).
First of all, the first key conclusion, if the result of our final construction meets the requirements of the title, there must be exactly one entry edge for each point.
Then notice that the value of k is very small, we can enumerate k violently by dfs, and then there is a question of the final result of the check.

During the match, I directly use the bool array to simulate... The pruning passed the pretest, and the tle retested after the match...Here we need to use hash to optimize the final check, and it is complicated to do O(1) check for each enumeration. degree.

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

struct Node
{
    
    
    ll to,weight;
};

vector<Node>field[maxn];
vector<ll>sum[10];
vector<ll>hash1[10],hash2[10];//hash[i][j]代表对于出度为i的点,我们选择第j小的边的时候,对应hash函数的增加值,用于dfs过程中O(1)计算
ll n,m,k;
ll ans=0;
ll tar1,tar2;//两个hash函数的最终结果,tar1为累加1到n的i三次方结果,tar2位累加1到n的i二次方结果

bool cmp(Node a,Node b)
{
    
    
    return a.weight<b.weight;
}

void dfs(ll deep,ll tot1,ll tot2)//tot1为第一个hash函数的统计结果,tot2为第二个hash函数的统计结果
{
    
    
    if(deep==k+1)
    {
    
    
        if(tot1==tar1&&tot2==tar2) ans++;//两个hash函数check结果都满足,判定所有点都被走到过了
        return ;
    }
    for(ll i=0;i<deep;i++)
    {
    
    
        dfs(deep+1,tot1+hash1[deep][i],tot2+hash2[deep][i]);//这里用hash优化了......
    }
}

int32_t main()
{
    
    
    IOS;
    cin>>n>>m>>k;
    for(ll i=0;i<m;i++)
    {
    
    
        ll u,v,w;
        cin>>u>>v>>w;
        field[u].push_back({
    
    v,w});
    }
    for(ll i=1;i<=n;i++)
    {
    
    
        tar1+=i*i*i;
        tar2+=i*i;
        sort(field[i].begin(),field[i].end(),cmp);
        sum[field[i].size()].push_back(i);
    }
    for(ll i=1;i<=k;i++)
    {
    
    
        for(ll j=0;j<i;j++)
        {
    
    
            unordered_map<ll,ll>M;
            ll temp1=0,temp2=0;
            for(auto &x:sum[i])
            {
    
    
                ll to=field[x][j].to;
                if(M.find(to)==M.end())
                {
    
    
                    temp1+=to*to*to;
                    temp2+=to*to;
                }
                M[to]=1;
            }
            hash1[i].push_back(temp1);
            hash2[i].push_back(temp2);
        }
    }
    dfs(1,0,0);
    cout<<ans<<endl;
}

Guess you like

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