Codeforces Round #575 (Div. 3)

Posted bluefly-hrbust

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #575 (Div. 3)相关的知识,希望对你有一定的参考价值。

  出题:A-B-D1-D2

  补题:C-E-F

  总结:B看错题,导致浪费非常多的时间,D2用前缀和分成三个写就超时,可能是我姿势不对。。。逃,心态炸了没读读懂C。。。还是太辣鸡了

  A. Three Piles of Candies

技术图片
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
  long long a,b,c;
  int n;
  while(~scanf("%d",&n))
    while(n--)
     scanf("%lld%lld%lld",&a,&b,&c);
     printf("%lld\n",(a+b+c)/2);
    
  
  return 0;
View Code

B. Odd Sum Segments

技术图片
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
const int maxx = 2e5+6;
int a[maxx];
int main()
  int t;
  int n,k;
  scanf("%d",&t);
  while(t--)
      vector<int>pos;
      scanf("%d%d",&n,&k);
      int cnt=0;
      for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        if (a[i]%2==1)
            cnt++;
            pos.push_back(i);
        
      
      if (cnt<k || (cnt-k)%2==1)
        printf("NO\n");
      else 
        int s=1;
        printf("YES\n");
        for (int i=1;i<pos.size();i++)
                if (s==k)break;
                printf("%d ",pos[i]-1);
                s++;
        
        printf("%d\n",n);
      
  
  return 0;
View Code

C. Robot Breakout

技术图片
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
int main()
  int t,n;
  scanf("%d",&t);
  while(t--)
    scanf("%d",&n);
    int x,y;
    int max_x=1e5,max_y=1e5,min_x=-1e5,min_y=-1e5;
    int a,b,c,d;
    for (int i=1;i<=n;i++)
        scanf("%d%d",&x,&y);
        scanf("%d%d%d%d",&a,&b,&c,&d);
        if (a==0)
            min_x=max(min_x,x);
        
        if (b==0)
            max_y=min(max_y,y);
        
        if (c==0)
            max_x=min(max_x,x);
        
        if (d==0)
            min_y=max(min_y,y);
        
    
    if (max_x<min_x || max_y<min_y)
            printf("0\n");
        else 
            printf("1 %d %d\n",max_x,max_y);
        
    
  
  return 0;
View Code

D1. RGB Substring (easy version)

技术图片
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxx = 2e5+6;
char str[maxx];
int main()
  int t;
  scanf("%d",&t);
  int len,n;
  while(t--)
      scanf("%d%d",&n,&len);
      scanf("%s",str);
      int ans=0;
      for (int i=0;i<n-len+1;i++)
          int cnt=0;
          for (int j=1;j<=3;j++)
              cnt=0;
              if (j==1)
                 for (int k=0;k<len;k++)
               //     cout<<i+k<<" ";
                    if (k%3==0 && str[i+k]==B)cnt++;
                    if (k%3==1 && str[i+k]==R)cnt++;
                    if (k%3==2 && str[i+k]==G)cnt++;
                 
              else if (j==2)
                for (int k=0;k<len;k++)
             //       cout<<i+k<<" ";
                    if (k%3==0 && str[i+k]==R)cnt++;
                    if (k%3==1 && str[i+k]==G)cnt++;
                    if (k%3==2 && str[i+k]==B)cnt++;
                 
              else 
                 for (int k=0;k<len;k++)
             //       cout<<i+k<<" ";
                    if (k%3==0 && str[i+k]==G)cnt++;
                    if (k%3==1 && str[i+k]==B)cnt++;
                    if (k%3==2 && str[i+k]==R)cnt++;
                 
              
          //    cout<<endl;
            //  cout<<cnt<<endl;
                      ans=max(ans,cnt);
          
      
      printf("%d\n",len-ans);
  
  return 0;
View Code

D2. RGB Substring (hard version)

三种情况的三种不同前缀和,最后查询一遍即可

技术图片
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxx = 2e5+6;
char str[maxx];
int pre[maxx][3];
int main()

    int t;
    scanf("%d",&t);
    int len,n;
    while(t--)
    
        scanf("%d%d",&n,&len);
        scanf("%s",str+1);
        for (int i=1; i<=n; i++)
        
            pre[i][0]=0;
            pre[i][1]=0;
            pre[i][2]=0;
        
        int cnt1=0;
        int cnt2=0;
        int cnt3=0;
        for (int i=1; i<=n; i++)
        
            if ((i-1)%3==0)
            
                if (str[i]==R)cnt1++;
                if (str[i]==G)cnt2++;
                if (str[i]==B)cnt3++;
                pre[i][0]=cnt1;
                pre[i][1]=cnt2;
                pre[i][2]=cnt3;
            
            else if ((i-1)%3==1)
            
                if (str[i]==G)cnt1++;
                if (str[i]==B)cnt2++;
                if (str[i]==R)cnt3++;
                pre[i][0]=cnt1;
                pre[i][1]=cnt2;
                pre[i][2]=cnt3;
            
            else
            
                if (str[i]==B)cnt1++;
                if (str[i]==R)cnt2++;
                if (str[i]==G)cnt3++;
                pre[i][0]=cnt1;
                pre[i][1]=cnt2;
                pre[i][2]=cnt3;
            
        
        int ans=0;
        for (int j=1; j<=n-len+1; j++)
        
            int w=max(pre[j+len-1][0]-pre[j-1][0],max(pre[j+len-1][1]-pre[j-1][1],pre[j+len-1][2]-pre[j-1][2]));
            ans=max(ans,w);
        
        printf("%d\n",len-ans);
    
    return 0;
View Code

 

E. Connected Component on a Chessboard

假如B<W,那么我们可以通过尽量构造1黑周围3个白,让差值减小2。不断减小

 当然如果差值为1的时候,我们可以通过构造1黑周围2个白,差值减小1,然后使得B和W的个数相同

 这个时候,直接B和W之间相邻构造就行了。

 然后把坐标保存下来,如果B>W个数,我们仍然按照上述构造,然后全部横坐标+1即可。

 也就是说,我们构造一条竖线,一定是黑白相间的,我们在竖线周围加上黑或者白多的那个,这样构造出来。

 动笔画画图就出来了。。。

技术图片
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define pii pair<int,int>
#define mp make_pair
using namespace std;
vector<pii> ans;
int main()

    int t,b,w;
    scanf("%d",&t);
    while(t--)
    
        scanf("%d%d",&b,&w);
        int three=0,two=0,one=0;
        ans.clear();
        int flag=0;
        if (b>w)
        
            flag=1;
            swap(b,w);
        
        if (3*b+1<w)
        
            printf("NO\n");
        
        else
        
            printf("YES\n");
            int s_x=2,s_y=3;
            while(w>=1 && b>=1)
            
                if (w-b>=2)
                
                    ans.push_back(mp(s_x,s_y));
                    ans.push_back(mp(s_x+1,s_y));
                    ans.push_back(mp(s_x-1,s_y));
                    ans.push_back(mp(s_x,s_y+1));
                    w-=3;
                    b-=1;
                    s_y+=2;
                
                else if (w-b>=1)
                
                    ans.push_back(mp(s_x,s_y));
                    ans.push_back(mp(s_x,s_y+1));
                    ans.push_back(mp(s_x+1,s_y));
                    w-=2;
                    b-=1;
                    s_y+=2;
                
                else
                
                    ans.push_back(mp(s_x,s_y));
                    ans.push_back(mp(s_x,s_y+1));
                    w-=1;
                    b-=1;
                    s_y+=2;
                
            
            if (w==1)
            
                ans.push_back(mp(2,2));
            
            if (flag)
            
                for (int i=0; i<ans.size(); i++)
                
                    printf("%d %d\n",ans[i].first,ans[i].second+1);
                
            
            else
            
                for (int i=0; i<ans.size(); i++)
                
                    printf("%d %d\n",ans[i].first,ans[i].second);
                
            
        
    
    return 0;
View Code

F. K-th Path

这个题是个好题啊,点赞,题目就说是,给一些点,以及一些边,我们需要找出这些点集之间的第K短的路。

。。。拿到就没什么想法,暴力弗洛伊德在1e5数据的下面,显然不现实,也没啥好的想法。。。

后面大佬代码,看到一位大佬非常优秀的代码。

考虑这样一个东西K,K实在太小了,小到只有400,那么其实你可以想到,我们的最坏情况,就是把边排序后的第400条边。

我们把这K条边重新建图,那么这图就小的可怜了。。。

点集不超过200,那么nlogn的最短路也就绰绰有余了。

跑完最短路后,枚举点之间距离,放入小根堆,最后丢掉前K-1个即可

技术图片
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#define pii pair<int,int>
#define pli pair<long long,int>
#define mp make_pair
#define LL long long
using namespace std;
const int maxx = 2e5+6;
const LL INF = 1e18;
struct node
  int x,y,w;
a[maxx];
int order[maxx];
struct Edge
  int v,w,n;
edge[maxx];
bool cmp(node a,node b)
   return a.w<b.w;

int tot;
int head[maxx];
LL dis[maxx];
bool vis[maxx];
void add(int x,int y,int z)
   edge[++tot]=(Edge)y,z,head[x];
   head[x]=tot;

void dij(int s)
   priority_queue<pli>q;
   for (int i=1;i<=2e5+4;i++)
       dis[i]=INF;
   
   memset(vis,0,sizeof(vis));
   q.push(mp(0,s));
   dis[s]=0;
   int x,y;
   while(q.size())
         x=q.top().second;
         q.pop();
         if (vis[x])continue;
         vis[x]=1;
      for (int i=head[x];i;i=edge[i].n)
         y=edge[i].v;
         if (dis[y]>dis[x]+edge[i].w)
             dis[y]=dis[x]+edge[i].w;
             q.push(mp(-dis[y],y));
         
      
   

int main()
  int n,m,k;
  while(~scanf("%d%d%d",&n,&m,&k))
      tot=1;
      memset(head,0,sizeof(head));
      memset(vis,0,sizeof(vis));
      memset(edge,0,sizeof(edge));
      for (int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
      
      sort(a+1,a+1+m,cmp);
      int cnt=0;
      for (int i=1;i<=min(k,m);i++)
          add(a[i].x,a[i].y,a[i].w);
          add(a[i].y,a[i].x,a[i].w);
          if (!vis[a[i].x])vis[a[i].x]=1,order[++cnt]=a[i].x;
          if (!vis[a[i].y])vis[a[i].y]=1,order[++cnt]=a[i].y;
      
      priority_queue<LL>ans;
      while(ans.size())ans.pop();
      for (int i=1;i<=cnt;i++)
          dij(order[i]);
          for (int j=i+1;j<=cnt;j++)
             ans.push(-dis[order[j]]);
          
      
      for (int i=1;i<k;i++)
        ans.pop();
      
      printf("%lld\n",-ans.top());
  
  return 0;
View Code

 

以上是关于Codeforces Round #575 (Div. 3)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #575 (Div. 3)

Codeforces Round #575 (Div. 3) C. Robot Breakout (模拟,实现)

Codeforces Round #575 (Div. 3) D1. RGB Substring (easy version)

Codeforces Round #575 (Div. 3) RGB Substring (hard version) ( FFT)

Codeforces Round #575 (Div. 3) B. Odd Sum Segments (构造,数学)

Codeforces Round #575 (Div. 3) (A. Three Piles of Candies)(数学)