Summary of week 2021-11-12

Weekly summary

A:

Problem - 1334C - Codeforces

Greedy question, xs, I thought it was dp at first glance, and then gave up decisively. At the end of the game, I asked hls what the transfer equation was. As a result, hls told me it was greedy, whine whine (although I felt I couldn't get out of it)

Meaning:

Some monsters have two attributes: blood volume and explosion damage after death. They form a ring. The explosion after death of the previous one will cause explosion damage to the latter one (chain). Ask how much blood volume you need to hit at least to kill them all.

Idea:

If I blow up the i-th monster first, then the i+1 monster I will blow up next time must be the i+1 monster, because in any case, my i+1 monster will be blown up. If I don't blow up now, I will kill the i+2 Monster by hand, but if I blow up the i+1 monster now, the i+2 monster will suffer explosion damage, and the cost of my hand will be small, So the process of simulating this problem is that I choose one to explode, and then continue to explode the next until there is no one. This turns into the question of determining the starting point. Who should we choose as the starting point? Of course, I choose the one with the smallest difference between the price I hit by hand and the price I hit again after the explosion. Reason: simulate the calculation process, you will find that except that the first contribution to the answer is blood, all other contributions to the answer are blood - the previous explosion damage, so we assume that there is no starting point, The answer is that the blood volume of all Monsters - the sum of the previous explosion damage is a fixed value. Now I have a starting point, which is equivalent to reducing the blood volume of the starting point - the previous explosion damage, and then adding the blood volume of the starting point. That is to minimize the difference between the two and the increment.

 #include <bits/stdc++.h>
 using namespace std;
 #define ll long long
 struct node{
     ll a,b;
     ll mar;
 };
 node x[300001];
 int main(){
     //No, the stream synchronization will be sent. I t sent it once
     std::ios::sync_with_stdio(false);
     ll t;
     cin>>t;
     while(t--){
         ll n;
         cin>>n;
         for(ll i=0;i<n;i++){
             cin>>x[i].a>>x[i].b;
             if(i!=0){
                 x[i].mar=max(0LL,x[i].a-x[i-1].b);
             } 
         }
         ll ans=0;
         //long long 0x3f3f3f3f is not enough. Let's have a few more. We'll do it again here
         ll ma=0x3f3f3f3f3f3f,maxindex=0;
         x[0].mar=max(0LL,x[0].a-x[n-1].b);
         for(ll i=0;i<n;i++){
             if(x[i].a-x[i].mar<ma){
                 ma=min(x[i].a-x[i].mar,ma);
                 maxindex=i;
             }
         }
         ans=x[maxindex].a;
         for(int i=0;i<n;i++){
             if(i==maxindex){
                 continue;
             }   
             ans+=x[i].mar;
         }
         cout<<ans<<endl;
     }   
     return 0;
 }

B:

Problem - 1372C - Codeforces

I actually did the water question, but I forgot to do it myself. I feel very familiar and just a.

Meaning:

Give you a string number to sort. You can select a continuous string at a time and change it into a new string that is not in its original position. Ask how many steps it takes to complete the sorting.

Idea:

The answer is only 0, 1, 2, 0. Needless to say, it was originally ordered. 1 is that there is only a string of consecutive numbers out of order, and none of the disordered numbers is where it should be. In the case of 2, I can't find the string of 1, or there are multiple strings that meet the condition of 1. Then I can directly select the whole string in the box and transform it twice, because the total situation of each string is the full arrangement of n, and I'm the second A transformation can certainly turn it into a string satisfying 1, and then it becomes 1.

It may be a trick to eliminate the numbers at both ends that are already in their own position, so that the only string to be processed is the middle section.

#include <bits/stdc++.h>
 using namespace std;
 #define ll long long 
 int x[200001];
 int main(){
     std::ios::sync_with_stdio(false);
     int t;
     cin>>t;
     while(t--){
         int n;
         cin>>n;
         for(int i=0;i<n;i++){
             cin>>x[i];
         }
         int flag=1;
         int i=0;
         int j=n-1;
         while(x[i]==i+1){
             i++;
         }
         while(x[j]==j+1){
             j--;
         }
         if(i>j){
             cout<<0<<endl;
             continue;
         }
         for(;i<=j;i++){
             if(x[i]==i+1){
                 flag=0;
                 break;
             }
         }
         if(flag==0){
             cout<<2<<endl;
         }else{
             cout<<1<<endl;
         }
     }   
     return 0;
 } 

C:

Problem - 1372D - Codeforces

Ouch, Han dad tql, I asked 2100. I thought it was a simulation of priority queue, but everyone was stupid.

Meaning:

Give you a ring with odd numbers. Choose one at a time and replace it with the sum of two adjacent numbers. Ask what is the maximum value of the last number

Idea:

If I want to maximize the last remaining number, I must find a way to make this number composed of as many numbers as possible. If I simulate this process, I will find that the last remaining number is composed of (n+1)/2 numbers in the original ring at most, and the arrangement of these (n+1)/2 numbers in the original ring must be separated by one between two, and there are and only two adjacent numbers (because it's a ring) My problem is how to find the largest number that satisfies the above conditions among these numbers, but you will find it difficult to find it directly. The reason is that it has a number that can be taken adjacent. Let's think from another angle. I take one every other time, and the parity of the subscripts of these numbers must be the same. When I select an adjacent number, it will be followed The parity of the subscripts of the re selected numbers is all opposite, and then a wonderful idea came. I tried to make the substring with the length of (n+1)/2 each time I took the ruler only and must select a pair of adjacent numbers, in other words, make the distance between each two adjacent numbers just be (n+1)/2-1, then according to the parity analyzed above, we can construct such a string: {A1, A3, A5.... an, A2, A4,... A (n-1)}, so that the above conditions are met when the ruler is taken (Miao frog, Miao frog, I call tql directly).

 #include <bits/stdc++.h>
 using namespace std;
 #define ll long long
 int x[200001];
 int y[200001];
 int main(){
     int n;
     cin>>n;
     for(int i=1;i<=n;i++){
         cin>>x[i];
     }
     int i=1;
     for(;i<=n;i++){
         y[i]=x[2*i-1];
         if(2*i-1==n){
             break;
         }
     }
     for(int j=2;j<=n;j+=2){
         y[++i]=x[j];
     }
     ll now=0;
     i=1;
     int j=1;
     for(;j<=(n+1)/2;j++){
         now+=y[j]; 
     }
     ll ans=now;
     //Ruler taking, that is, double pointers, no one can't write ruler taking
     for(;i<=n;i++){
         now=now-y[i]+y[j++];
         ans=max(ans,now);
         //Small details, j has not finished searching the end, but i has to search the end, because it is a ring, and each may be the starting point of the target string
         if(j==n+1){
             j=1;
         }
     }
     cout<<ans<<endl;
     return 0;
 }

D:

Problem - 1454C - Codeforces

Check in question. I don't want to write the problem solution. Read it for myself. Judge the weight, traverse and judge the two ends. However, many people are stuck and don't understand it very well (although I wa it three times, shit, it's too fw).

 #include <bits/stdc++.h>
 using namespace std;
 #define ll long long 
 int x[200001];
 ​
 int num[200001];
 int main(){
     std::ios::sync_with_stdio(false);
     int t;
     cin>>t;
     while(t--){
         int n;  
         cin>>n;
         int nm=n;
         for(int i=0;i<=n;i++){
             num[i]=0;
         }
         for(int i=0;i<n;i++){
             cin>>x[i];
             if(i!=0&&x[i]==x[i-1]){
                 i--;
                 n--;
             }
         }
         if(n==1){
             cout<<0<<endl;
             continue;
         }
         for(int i=1;i<n-1;i++){
             if(num[x[i]]==0){
                 num[x[i]]++;
             }
             num[x[i]]++;
         }
         if(x[0]!=x[n-1]){
             if(num[x[0]]==0){
                 num[x[0]]++;
             }
             if(num[x[n-1]]==0){
                 num[x[n-1]]++;
             }
         }else{
             if(num[x[0]]==0){
                 num[x[0]]++;
             }           
         }   
         int ans=10000000;
         //I wa'm here. When I remove the weight, n becomes smaller, but the data range is still the original range of N, which is equivalent to not traversing here, Gan
         for(int i=1;i<=nm;i++){
             if(num[i]!=0){
                 ans=min(ans,num[i]);
             }
         }       
         if(ans==10000000){
             cout<<0<<endl;
             continue;
         }
         cout<<ans<<endl;    
     }
     return 0;
 } 

E:

Problem - 1421D - Codeforces

When hls opened the question, I glanced at the solution. I probably knew what it meant, but I felt that the code size was not small, lazy and didn't write,

F:

Problem - 1451E2 - Codeforces

Open the problem surface - > see bit operation (cool half) - > see interaction (give up decisively) - > make up questions after the game - > see 2300 - > get off the computer decisively and do your homework.

Tags: Algorithm greedy algorithm

Posted on Fri, 12 Nov 2021 20:28:21 -0500 by alco19357