la3716(*数学变形)

来源:互联网 发布:apache 允许目录列表 编辑:程序博客网 时间:2024/06/06 13:20
/*translation:    给出两条字符串A,B。找出一段最长的子区间,使得区间所有位置x,有不超过p%的位置存在A[x]!=B[x]solution:    利用数学变形    构造一个数列,两字符串相等的位置为0,不等的为1。另sum[i]为前缀和。则就是求    (sum[e]-sum[s])/(e-s)不超过p%的最长长度是多少?note:    * 看上去跟LA4726很像,但是方法不同。利用等式变形:(sum[r]-sum[l])/(r-l) <= p / 100      变为sum[r]∗100−r∗p≤sum[l]−l∗p.令val[i] = sum[i] * 100 - i * p;      若val[i]>=val[j] && i <= j的区间(i,j)才是合法区间。*/#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 150000 + 5;int vec[maxn], n, p;char a[maxn], b[maxn];int sum[maxn];bool hasSolution;struct Node{    int id, val;    Node(int id_, int val_):id(id_),val(val_){}    Node(){}    bool operator < (const Node& rhs) const {        return val > rhs.val || (val == rhs.val && id < rhs.id);    }} nodes[maxn];int main(){    //freopen("in.txt", "r", stdin);    while(~scanf("%d%d", &n, &p)) {        if(n + p == 0)  break;        scanf("%s%s", a + 1, b + 1);        memset(vec, 0, sizeof(vec));        int cnt = 0;        nodes[0].val = nodes[0].id = 0;        for(int i = 1; i <= n; i++) {            if(a[i] != b[i])    cnt++;            nodes[i].val = cnt * 100 - i * p;            nodes[i].id = i;        }        sort(nodes, nodes + 1 + n);        int ans = 0, id_min = nodes[0].id;        for(int i = 1; i <= n; i++) {            if(nodes[i].id < id_min)    id_min = nodes[i].id;            else    ans = max(ans, nodes[i].id - id_min);        }        if(ans) printf("%d\n", ans);        else    printf("No solution.\n");    }    return 0;}

0 0
原创粉丝点击