1451 - Average(数形结合)

该题表面让我们求一个字符串的问题,但是却可以转化成求斜率的问题, 紫书上已经说的很清楚了,我这里就不再赘述  。

代码如下 :

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 5;
int n,T,L;
double a[maxn],p[maxn];
char s[maxn];
int campare(int x1,int x2,int x3,int x4){   //直线p[x1]p[x2]的斜率减去p[x3]p[x4]的斜率
    return (a[x1] - a[x2-1])*(x3-x4+1) - (a[x3] - a[x4-1])*(x1-x2+1); 
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%s",&n,&L,s);
        int len = strlen(s);
        a[0] = 0;
        for(int i=0;i<len;i++){
            a[i+1] = a[i] + s[i] - '0'; //a[i]为前i项的和
        }
        int l = 1, r = L , i = 0 , j = 0; //用两个指针 i 和 j 来动态维护下凸区间。
        for(int t = L;t <= len;t ++) {
            while(j - i > 1 && campare(t-L,p[j-2],t-L,p[j-1])>=0) j--; //删除上凸的点
            p[j++] = t - L + 1; //增加新元素
            while(j - i > 1 && campare(t,p[i+1],t,p[i])>=0) i++; //确定新的切点,因为切点的x坐标一定是不断增加的
            int c = campare(r,l,t,p[i]);
            if(c < 0 || c == 0 && (r-l)>(t-p[i])) { 
                l = p[i] ; r = t ;
            }
        }
        cout<<l<<' '<<r<<endl;
    }
    return 0;
}


你可能感兴趣的:(ACM,uva)