【HDOJ6586】String(枚举)

题意:给定一个由小写字母组成的字符串S,要求从中选出一个长度为k的子序列,使得其字典序最小,并且第i个字母在子序列中出现的次数在[l[i],r[i]]之间

n,k<=1e5

思路:大概就是记一下后缀和然后逐位确定,把能想到的界都给卡上

这种题写错的话大概随机数据拍都能拍出来,就是调起来占大量机时并且体感极差就是了

 

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 typedef pair<ll,int>P;
 11 #define N  110000
 12 #define M  151000
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pi acos(-1)
 17 #define mem(a,b) memset(a,b,sizeof(a))
 18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 20 #define lowbit(x) x&(-x)
 21 #define Rand (rand()*(1<<16)+rand())
 22 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 23 #define ls p<<1
 24 #define rs p<<1|1
 25 
 26 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 27       double eps=1e-6;
 28       ll INF=1e18;
 29       ll inf=5e13;
 30       int dx[4]={-1,1,0,0};
 31       int dy[4]={0,0,-1,1};
 32 
 33 int s[N][26],nxt[N][26],ans[N],l[N],r[N],t[26],a[26],n,K;
 34 char ch[N];
 35 
 36 int read()
 37 {
 38    int v=0,f=1;
 39    char c=getchar();
 40    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 41    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 42    return v*f;
 43 }
 44 
 45 int isok(int x,int y,int z)
 46 {
 47     int t=nxt[x][z];
 48     //printf("x=%d y=%d z=%d t=%d\n",x,y,z,t);
 49     if(t==n+1) return 0;
 50     //if(K-y>n-t) return 0;
 51     if(a[z]+1>r[z]) return 0;
 52     a[z]++;
 53     //rep(i,0,3) printf("%d ",a[i]);
 54     //printf("\n");
 55     int tmp=0;
 56     rep(i,0,25) tmp+=min(s[t+1][i],r[i]-a[i]);
 57     //printf("tmp1=%d\n",tmp);
 58     if(tmp<K-y)
 59     {
 60         a[z]--;
 61         return 0;
 62     }
 63 
 64     rep(i,0,25)
 65      if(a[i]+min(s[t+1][i],min(n-t,K-y))<l[i])
 66      {
 67          a[z]--;
 68          return 0;
 69      }
 70 
 71     tmp=0;
 72     rep(i,0,25) tmp+=max(0,l[i]-a[i]);
 73     //printf("tmp2=%d\n",tmp);
 74     if(tmp>n-t||tmp>K-y)
 75     {
 76         a[z]--;
 77         return 0;
 78     }
 79     a[z]--;
 80     return 1;
 81 }
 82 
 83 int main()
 84 {
 85     //freopen("1.in","r",stdin);
 86     //freopen("1.out","w",stdout);
 87     while(scanf("%s",ch+1)!=EOF)
 88     {
 89         n=strlen(ch+1),K=read();
 90         if(K==0) break;
 91         rep(i,0,25) t[i]=n+1;
 92         rep(i,0,25) s[n+1][i]=0;
 93         per(i,n,0)
 94         {
 95             int x=0;
 96             if(i) x=ch[i]-'a';
 97             rep(j,0,25) nxt[i][j]=t[j];
 98             t[x]=i;
 99             rep(j,0,25) s[i][j]=s[i+1][j];
100             s[i][x]++;
101         }
102         rep(i,0,25) l[i]=read(),r[i]=read();
103         int flag=1;
104         rep(i,1,K) ans[i]=0;
105         rep(i,0,25) a[i]=0;
106         int now=0;
107         rep(i,1,K)
108         {
109             int k=26;
110             rep(j,0,25)
111              if(isok(now,i,j)){k=j; now=nxt[now][j]; a[j]++; break;}
112 
113             if(k==26){flag=0; break;}
114             ans[i]=k;
115             //printf("ans%d=%d now=%d\n",i,k,now);
116         }
117         //printf("flag=%d\n",flag);
118         if(flag)
119         {
120             rep(i,1,K) printf("%c",ans[i]+'a');
121             printf("\n");
122         }
123          else printf("-1\n");
124     }
125 
126     return 0;
127 }

 

posted on 2019-09-18 16:16  myx12345  阅读(235)  评论(0编辑  收藏  举报

导航