第一行七个整数n,a,b,c,d,l,r,其中n表示字符串的长度
第二行一行一个长度为n的字符串
第三行一行n个整数,表示每个字符的删除难度dif[I]
标签:sum scan 记录 前缀 scanf pre logs 电源 style
测试点编号
|
n
|
特殊约定
|
1
|
n≤10
|
所有的字母都是a
|
2
|
所有的字母都是a或b
|
|
3
|
||
4
|
||
5
|
n≤2000
|
所有的字母都是a
|
6
|
所有的字母都是a或b
|
|
7
|
l=1,r=n
|
|
8
|
||
9
|
||
10
|
||
11
|
n≤100000
|
l=1,r=n
|
12
|
||
13
|
||
14
|
||
15
|
l>r
|
|
16
|
||
17
|
||
18
|
||
19
|
||
20
|
所以就发现,维护dp[j]-c*sum[j]为关键字的最小值,然后剩下的就是如何判断是否合法,然后就没有了,如何判断呢?
就是记录一个前缀和,因为N为十万,那么最多有26个不同的字符,就开一个26*100000空间的数组,记录前缀和,然后每次26的复杂度
去判断合不合法,这样用堆或者单调队列维护最小值,就OK了。
我这里视同优先队列的。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #include<queue> 7 #define LL long long 8 #define fzy pair<LL,int> 9 #define N 100007 10 #define inf 1e9+7 11 12 using namespace std; 13 14 int n,a,b,c,d,l,r; 15 int qz[N][27],q[N]; 16 LL sum[N],dp[N]; 17 char ch[N]; 18 19 priority_queue<fzy,vector<fzy>,greater<fzy> >st; 20 LL get_x(int k,int j) 21 { 22 return dp[j]-dp[k]+a*sum[j]*sum[j]-a*sum[k]*sum[k]; 23 } 24 LL get_y(int k,int j) 25 { 26 return 2*a*(sum[j]-sum[k]); 27 } 28 bool pan(int x,int y) 29 { 30 int res=-inf; 31 for (int i=0;i<26;i++) 32 res=max(res,qz[y][i]-qz[x][i]); 33 if (res<=r&&res>=l) return true; 34 else return false; 35 } 36 int main() 37 { 38 // freopen("1.in","r",stdin); 39 // freopen("fzy.out","w",stdout); 40 41 scanf("%d%d%d%d%d%d%d",&n,&a,&b,&c,&d,&l,&r); 42 scanf("%s",ch+1); 43 int head=0,tail=0,id=0; 44 q[0]=0; 45 for (int i=1;i<=n;i++) 46 { 47 scanf("%d",&sum[i]); 48 for (int j=0;j<26;j++) qz[i][j]=qz[i-1][j]; 49 qz[i][ch[i]-‘a‘]++; 50 51 sum[i]+=sum[i-1]; 52 while (head+1<=tail&&(LL)get_x(q[head],q[head+1])<=(LL)get_y(q[head],q[head+1])*sum[i]) head++; 53 int t=q[head]; 54 dp[i]=dp[t]+a*(sum[i]-sum[t])*(sum[i]-sum[t])+b; 55 56 while (id<=i) 57 if (pan(id,i)) 58 { 59 st.push(make_pair(dp[id]-c*sum[id],id)); 60 id++; 61 } 62 else break; 63 while(!st.empty()) 64 { 65 fzy now=st.top(); 66 t=now.second; 67 if (pan(t,i)) 68 { 69 dp[i]=min(dp[i],dp[t]+c*(sum[i]-sum[t])+d); 70 break; 71 } 72 else 73 { 74 st.pop(); 75 continue; 76 } 77 } 78 79 while (head+1<=tail&&(LL)get_x(q[tail-1],q[tail])*get_y(q[tail],i)>=(LL)get_x(q[tail],i)*get_y(q[tail-1],q[tail])) tail--; 80 q[++tail]=i; 81 printf("%lld\n",dp[i]); 82 } 83 }
标签:sum scan 记录 前缀 scanf pre logs 电源 style
原文地址:http://www.cnblogs.com/fengzhiyuan/p/7537792.html