COJ 删除数字

 

试题描述
输入正整数N和M,在N中删除掉M位,能留下的最大整数是多少?
输入
正整数N和M
输出
留下的最大整数
输入示例
233390323 5
输出示例
9323
其他说明
1<=N<=10^1000
1<=M<=1000
 

N的长度比较小,胡搞就行了。

那么如果1<=N<=10^1000000呢?

考虑当前最后保留的位置是cur,还要删m个字符,那么下一个要删的区间应是[cur+1,cur+m+1],那么我们要设计一个数据结构快速找到区间最大值。

这显然是个滑动窗口,用单调队列做做就行了(<--WZJ这蒟蒻竟然没看出来写了线段树)。注意这组数据636546796 8要输出9,即如果最后还没删够要输出前n-m个得到的字符。

#include<cstdio>
#include<cctype>
#include<ctime>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
char s[1000010],q[1000010];
int maxv[3000010];
void build(int o,int l,int r) {
    if(l==r) maxv[o]=l;
    else {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        build(lc,l,mid);build(rc,mid+1,r);
        if(s[maxv[lc]]>=s[maxv[rc]]) maxv[o]=maxv[lc];
        else maxv[o]=maxv[rc];
    }
}
int ql,qr;
int query(int o,int l,int r) {
    if(ql<=l&&r<=qr) return maxv[o];
    int mid=l+r>>1,lc=o<<1,rc=lc|1;
    if(qr<=mid) return query(lc,l,mid);
    if(ql>mid) return query(rc,mid+1,r);
    int ans1=query(lc,l,mid),ans2=query(rc,mid+1,r);
    return s[ans1]>=s[ans2]?ans1:ans2;
}
int main() {
    int m,cnt=0,t;
    scanf("%s%d",s+1,&m);t=m;
    int n=strlen(s+1),cur=0;
    build(1,1,n);
    while(cur<n) {
        ql=cur+1;qr=min(cur+m+1,n);
        int next=query(1,1,n);
        m-=next-cur-1;cur=next;
        q[++cnt]=s[cur];if(m<=0) break;     
    }
    if(m) rep(i,1,n-t) putchar(q[i]);
    else {
         printf("%s",q+1);
         rep(i,cur+1,n) putchar(s[i]);     
    }
    return 0;    
}
View Code

 

posted @ 2015-07-09 15:47  wzj_is_a_juruo  阅读(217)  评论(0编辑  收藏  举报