zoukankan      html  css  js  c++  java
  • G

    题目
    题意:给出一个不含前前导零的字符串,要求删除m个字符(),使得该字符串数字值最小。
    1、单调队列解法:反过来看删除m个字符,就是留下m'(len-m)个字符,根据巢鸽原理,选择区间的右区间的端点从len-m'+1(闭区间)开始依次后移 ,
    而左区间为1或上次被选位置开始(开区间),从这m'个区间中选择最小数字,可得最小值。
    因为右端点是逐渐后移,与滑动窗口很类似,所以可以使用单调递减队列维护区间最小值。

    //#include<bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include <vector>
    #include <stdlib.h>
    #include <time.h>
    using namespace std;
    typedef long long ll ;
    #define int ll
    #define mod 1000000007
    #define gcd __gcd
    #define rep(i , j , n) for(int i = j ; i <= n ; i++)
    #define red(i , n , j)  for(int i = n ; i >= j ; i--)
    #define ME(x , y) memset(x , y , sizeof(x))
    //int lcm(int a , int b){return a*b/gcd(a,b);}
    //ll quickpow(ll a , ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;b>>=1,a=a*a%mod;}return ans;}
    //int euler1(int x){int ans=x;for(int i=2;i*i<=x;i++)if(x%i==0){ans-=ans/i;while(x%i==0)x/=i;}if(x>1)ans-=ans/x;return ans;}
    //const int N = 1e7+9; int vis[n],prime[n],phi[N];int euler2(int n){ME(vis,true);int len=1;rep(i,2,n){if(vis[i]){prime[len++]=i,phi[i]=i-1;}for(int j=1;j<len&&prime[j]*i<=n;j++){vis[i*prime[j]]=0;if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}else{phi[i*prime[j]]=phi[i]*phi[prime[j]];}}}return len}
    #define INF  0x3f3f3f3f
    #define PI acos(-1)
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define pb push_back
    #define mp make_pair
    #define all(v) v.begin(),v.end()
    #define size(v) (int)(v.size())
    #define cin(x) scanf("%lld" , &x);
    #define endl '
    '
    const double esp = 1e-6;
    const int N = 1e6+9;
    const int maxn = 2e5+9;
    char a[maxn];
    char q[maxn] ;
    int rear , front ;
    int n , m ;
    void solve(){
        int len = strlen(a+1);
        m = len - m ;
        rear = front = 0 ;
        vector<char>v;
        rep(i , 1 , len){
            while(rear != front && a[i] < q[rear]){
                rear--;
            }
            q[++rear] = a[i];
            if(i >= len-m+1){
                v.pb(q[++front]);
            }
        }
        while(size(v) && *v.begin() == '0') v.erase(v.begin());
        if(size(v) == 0) cout << 0 << endl;
        else{
            for(auto i : v){
                cout << i ;
            }
            cout << endl;
        }
    }
    
    signed main()
    {
        //int _ ;cin>>_;while(_--)
        while(~scanf("%s%lld" , a+1 , &m))
            solve();
    }
    
    

    2.RMQ解法:同上也是求m个区间的最小值,只是不同的实现。
    定义方程:(dp[i][j])表示起点为i长度为(2^j)的区间最小值
    RMQ主要思想是倍增:比如预处理1-4区间的最小值可通过1-2和3-4的最小值得出。小区间推出大区间。
    边界:(dp[i][0] = a[i])
    递推:(dp[i][j] = min(dp[i][j-1] , dp[i+(1<<(j-1))][j-1]);(i+2^j-1 <= len))
    查询操作:取长度(len = log_2(r-l+1)) , 结果为:(min(dp[l][len] , dp[r-(1<<(len))+1][len]))

    //#include<bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include <vector>
    #include <stdlib.h>
    #include <time.h>
    using namespace std;
    typedef long long ll ;
    #define int ll
    #define mod 1000000007
    #define gcd __gcd
    #define rep(i , j , n) for(int i = j ; i <= n ; i++)
    #define red(i , n , j)  for(int i = n ; i >= j ; i--)
    #define ME(x , y) memset(x , y , sizeof(x))
    //int lcm(int a , int b){return a*b/gcd(a,b);}
    //ll quickpow(ll a , ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;b>>=1,a=a*a%mod;}return ans;}
    //int euler1(int x){int ans=x;for(int i=2;i*i<=x;i++)if(x%i==0){ans-=ans/i;while(x%i==0)x/=i;}if(x>1)ans-=ans/x;return ans;}
    //const int N = 1e7+9; int vis[n],prime[n],phi[N];int euler2(int n){ME(vis,true);int len=1;rep(i,2,n){if(vis[i]){prime[len++]=i,phi[i]=i-1;}for(int j=1;j<len&&prime[j]*i<=n;j++){vis[i*prime[j]]=0;if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}else{phi[i*prime[j]]=phi[i]*phi[prime[j]];}}}return len}
    #define INF  0x3f3f3f3f
    #define PI acos(-1)
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define pb push_back
    #define mp make_pair
    #define all(v) v.begin(),v.end()
    #define size(v) (int)(v.size())
    #define cin(x) scanf("%lld" , &x);
    #define endl '
    '
    const double esp = 1e-6;
    const int N = 1e6+9;
    const int maxn = 1e3+9;
    int dp[maxn][30];
    char a[maxn];
    int m ;
    int len ;
    int min(int x , int y){
        if(a[x] > a[y]) return y ;
        else return x ;
    }
    
    void init(){
        rep(i , 1 , len){
            dp[i][0] = i ;
        }
        for(int j = 1 ; j <= 10 ; j++){
            for(int i = 1 ; i+(1<<j)-1 <= len ; i++){
                dp[i][j] = min(dp[i][j-1] , dp[i+(1<<(j-1))][j-1]);
            }
        }
    }
    
    int query(int l , int r){
        int len = log2(r-l+1);
        return min(dp[l][len] , dp[r-(1<<(len))+1][len]);
    }
    
    void solve(){
        len = strlen(a+1);
        init();
        m = len - m ;
        int l = 1 , r = len-m+1;
        vector<char>v;
        while(m--){
            l = query(l , r) ;
            v.pb(a[l]);
            l++;
            r++;
        }
        while(size(v) && *v.begin() == '0') v.erase(v.begin());
        if(size(v) == 0) cout << 0 << endl;
        else{
            for(auto &i : v){
                cout << i ;
            }
            cout << endl;
        }
    }
    
    signed main()
    {
        //int _ ;cin>>_;while(_--)
        while(~scanf("%s%lld" , a+1 , &m))
            solve();
    }
    
    
  • 相关阅读:
    常用MySQL函数连接
    spring boot和mybatis的多源配置亲测可用非常简单哦铁闸门
    RestTemplate请求发送post请求携带数组参数(亲测有效)
    idea配置tomcat
    前后端分离生成手机验证码
    前后端分离的图片验证保存及发送方式
    Java—大文件分片上传
    SpringAOP实战
    Spring Boot AOP的使用
    iOS开发日常记录
  • 原文地址:https://www.cnblogs.com/nonames/p/12884360.html
Copyright © 2011-2022 走看看