zoukankan      html  css  js  c++  java
  • #601 (Div. 2)

    Codeforces Round #601 (Div. 2)

    C - League of Leesins
    • 题意:有一个由数字1~n构成的序列,现在给你这个序列所有相邻3个数的值,他们不一定按顺序。现在要根据这些值输出原序列。有多解输出其中一个。如,具体见下图样例。

    • 分析:

      • 简单想一想就可以发现如果你知道ans[i-2],ans[i-1],那么就可以唯一确定ans[i]。当然第一个值p1和第二个值p2可以用各种方法都能得到,但是当想要用p1,p2确定下一个值时就不能遍历去却确定了。所以整道题的关键就变成了如何快速根据前面两个值去确定下一个值。
      • 仔细想想维护由两个值确定一个值,而且这两个值还有可能确定其他值挺麻烦的,但是如果你发现其实每一行输入处了三个值外还有一个被忽略的值,那就是这三个值输入的位置(在数组中的下标)。
      • 那么每次输入a,b,c。我们可以给他们维护所在下标,即每个值在第几个3元集中出现过。这样那个只出现一次的值就是p1,根据p1所在下标,找出现2次的数就是p2。就很容易了。
      • 这时候就会发现一定有一个3元集中包含ans[i-2],ans[i-1],ans[i]。所以你在确定ans[i]时只需要找到这个3元集的下标就好办了。由于是从前面更新过来的,所以当你处理ans[i-2],ans[i-1],ans[i]时,ans[i-2]的其他所在3元集一定已经处理过了。所以只要你之前用标记数组vis标记已经处理的3元集下标,现在只要确定ans[i-2]中那个还没有处理的下标就是你要用来确定ans[i]的。具体见代码。
    • 代码:

      #include<bits/stdc++.h>
      using namespace std;
      typedef long long ll;
      const int MA=1e5+15;
      
      int n,p1,p2,New;
      int a[MA],b[MA],c[MA];
      vector<int>index[MA];
      vector<int>ans;
      int vis[MA];
      
      void in()
      {
          scanf("%d",&n);
          for(int i=1;i<=n-2;++i){
              scanf("%d%d%d",&a[i],&b[i],&c[i]);
              index[a[i]].push_back(i);
              index[b[i]].push_back(i);
              index[c[i]].push_back(i);
          }
          for(int i=1;i<=n;++i){
              if(index[i].size()==1){
                  p1=i;
                  New=index[i][0];
                  break;
              }
          }
      }
      
      void findp2()
      {
              int i=index[p1][0];
              if(a[i]==p1){
                 if(index[b[i]].size()==2){
                      p2=b[i];
                 }
                 else {
                      p2=c[i];
                 }
              }
              if(b[i]==p1){
                 if(index[a[i]].size()==2){
                      p2=a[i];
                 }
                 else {
                      p2=c[i];
                 }
              }
              if(c[i]==p1){
                 if(index[a[i]].size()==2){
                      p2=a[i];
                 }
                 else {
                      p2=b[i];
                 }
              }
      }
      
      void update_New(int x)
      {
          for(int i=0;i<index[x].size();++i){
              int idx=index[x][i];
              if(!vis[idx]){
                  New=idx;
                  break;
              }
          }
      }
      
      int main()
      {
          in(); //输入并确定p1
          ans.push_back(p1);
          findp2(); //确定p2
          ans.push_back(p2);
      
          for(int i=3;i<=n;++i){
              int other=a[New]+b[New]+c[New]-ans[i-3]-ans[i-2]; //由ans[i-3],ans[i-2],确定ans[i-1]
              vis[New]=1;             //标记用过的下标
              update_New(ans[i-2]);   //更新New
              ans.push_back(other);
          }
      
          for(int i=0;i<ans.size();++i){
              if(i==n-1) printf("%d
      ",ans[i]);
              else printf("%d ",ans[i]);
          }
          return 0;
      }
      
      
      
  • 相关阅读:
    C# 控制反转
    控制反转和依赖注入
    C#中使用AOP
    jquery ajax
    python(7)- 小程序练习:循环语句for,while实现99乘法表
    007所谓性格与条件并不是成功的阻碍,懦弱才是
    006学习有可能速成吗
    005自学与有人带着哄着逼着学的不同在于自学是一种成熟的自律
    005单打独斗意味着需要更好地管理自己
    004真正的教育是自我教育,真正的学习是自学
  • 原文地址:https://www.cnblogs.com/A-sc/p/12128348.html
Copyright © 2011-2022 走看看