zoukankan      html  css  js  c++  java
  • Codeforces 1023 D.Array Restoration-RMQ(ST)区间查询最值 (Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Fi)

    D. Array Restoration

    这题想一下就会发现是只要两个相同的数之间没有比它小的就可以,就是保存一下数第一次出现和最后一次出现的位置,然后查询一下这个区间就可以,如果有0的话就进行填充。

    这个题我是用RMQ(ST)进行查询的,在初始化的时候,如果有0就把0变成2e5+1,因为数据最大2e5,然后区间查询就可以了,关于RMQ(ST),以前写过博客,有兴趣的可以看一下

    RMQ(ST)详解

    这个题坑点很多,首先如果这个序列一开始的最大值比m小,并且没有0,那么就是NO,有0就先把一个0变成m,然后填充的时候,如果一开始的最大值就是0,说明全部为0,那么直接把所有0变成m然后输出就可以了。其他的具体的看代码吧,写了注释。

    代码:

      1 //D-区间查询最值,RMQ查询
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<bitset>
      7 #include<cassert>
      8 #include<cctype>
      9 #include<cmath>
     10 #include<cstdlib>
     11 #include<ctime>
     12 #include<deque>
     13 #include<iomanip>
     14 #include<list>
     15 #include<map>
     16 #include<queue>
     17 #include<set>
     18 #include<stack>
     19 #include<vector>
     20 using namespace std;
     21 typedef long long ll;
     22 
     23 const double PI=acos(-1.0);
     24 const double eps=1e-6;
     25 const ll mod=1e9+7;
     26 const int inf=0x3f3f3f3f;
     27 const int maxn=2*1e5+10;
     28 const int maxm=100+10;
     29 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     30 
     31 int a[maxn],mm[maxn][maxm],mi[maxn][maxm];
     32 int n,m,MIN,MAX;
     33 
     34 void ST()
     35 {
     36     for(int i=1;i<=n;i++){
     37         if(a[i]!=0)
     38             mm[i][0]=mi[i][0]=a[i];
     39         else
     40             mm[i][0]=mi[i][0]=2*1e5+1;//把0变成最大的
     41     }
     42     for(int j=1;(1<<j)<=n;j++){
     43         for(int i=1;i+(1<<j)-1<=n;i++){
     44             mm[i][j]=max(mm[i][j-1],mm[i+(1<<(j-1))][j-1]);
     45             mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
     46         }
     47     }
     48 }
     49 
     50 void RMQ(int l,int r)
     51 {
     52     int k=0;
     53     while((1<<(k+1))<=r-l+1)k++;
     54     MAX=max(mm[l][k],mm[r-(1<<k)+1][k]);
     55     MIN=min(mi[l][k],mi[r-(1<<k)+1][k]);
     56 }
     57 
     58 vector<int> vec[maxn];//保存数出现的所有位置
     59 
     60 int main()
     61 {
     62     cin>>n>>m;
     63     int flag=0,maxx=-1,pos=0;
     64     for(int i=1;i<=n;i++){
     65         cin>>a[i];
     66         maxx=max(maxx,a[i]);
     67         if(a[i]==0)pos=i;
     68         vec[a[i]].push_back(i);
     69     }
     70     if(maxx<m&&maxx>0&&pos!=0) a[pos]=m;//如果一开始所有数都小于m,就把一个0变成m
     71     else if(maxx==0){//如果所有数都为0,直接全变成0然后输出就可以了
     72         for(int i=1;i<=n;i++)
     73             a[i]=m;
     74         cout<<"YES"<<endl;
     75         for(int i=1;i<=n-1;i++)
     76             cout<<a[i]<<" ";
     77         cout<<a[n]<<endl;
     78         return 0;
     79     }
     80     else if(maxx<m&&pos==0){//如果最大值小于m并且没有0,就是NO
     81         cout<<"NO"<<endl;
     82         return 0;
     83     }
     84     ST();
     85     for(int i=1;i<=m;i++){
     86         if(vec[i].size()!=0){
     87             int l=vec[i][0];//值为i的数第一次出现的位置
     88             int r=vec[i][vec[i].size()-1];//最后一次出现的位置
     89             RMQ(l,r);
     90             if(MIN<i){//查询区间的最小值
     91                 flag=1;
     92                 break;
     93             }
     94         }
     95     }
     96     if(flag==1){
     97         cout<<"NO"<<endl;
     98         return 0;
     99     }
    100     for(int i=1;i<=n;i++){
    101         if(a[i]==0){
    102             for(int j=i+1;j<=n;j++){//从当前位置找第一个不为0的数
    103                 if(a[j]==0) continue;
    104                 else{
    105                     a[i]=a[j];
    106                     break;
    107                 }
    108                }
    109             if(a[i]==0) a[i]=a[i-1];//如果右端点全为0,就填充左边的数
    110            }
    111     }
    112     cout<<"YES"<<endl;
    113     for(int i=1;i<=n-1;i++)
    114         cout<<a[i]<<" ";
    115     cout<<a[n]<<endl;
    116 }

    嘤嘤嘤,溜了。

  • 相关阅读:
    近期需要学习的
    sdfsdf
    思路绝对清楚,手段绝对下流【转】
    一宅镇京华——看谁还敢在我面前吹丫有钱 
    白天求生存,晚上求发展
    Ten Places to Go for SharePoint Development Information
    Life Record
    Custom Search Result Style Based On SharePoint Xslt Search Result Style
    软考信息系统项目管理师考试记录
    什么是Microsoft SharePoint 2010
  • 原文地址:https://www.cnblogs.com/ZERO-/p/9703714.html
Copyright © 2011-2022 走看看