hdu 4339 线段树+二分

来源:互联网 发布:基础编程入门教程 编辑:程序博客网 时间:2024/09/21 09:02

本人此方法很搓。。。大多数人的做法和我不一样,时间比我快一倍。这道题是一个非常好的题,首先是他的数据量非常大,这就提示我们要做一些优化。。而本题又是在字符串的基础上设计算法,字符串有很多细节还是必须要注意的。。题意很简单,这里略掉。拿到两个字符串后,首先是圈定线段树的宽度,即两个字符串长度的最短值,不再范围内的字符不会影响结果。接下来就是如何处理query,把两个字符串相减后发现,所求的即从i后最多有多少连续个0。怎么办?貌似用最直接的方法做很费劲,而且不保险,二分!!!求最大点,计算quary,每个线段节点的值等于它的左子树和右子树的值取或。。附带码:

#include <iostream>#include <cmath> using namespace std;#define clear(a) memset(a,0,sizeof(a))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1 const int N=1001000;int sum[N<<2],a[N],k,n,n0;char s1[N],s2[N];void pushup(int rt){    sum[rt]=sum[rt<<1]||sum[rt<<1|1];}void build(int l,int r,int rt){    if (l==r)    {        ++k;        sum[rt]=a[k];        return;    }    int m=(l+r)>>1;    build(lson);    build(rson);    pushup(rt);}int query(int L,int R,int l,int r,int rt){    if (L<=l&&r<=R)    {        return sum[rt];    }    int m=(l+r)>>1,res=0;    if (L<=m) res=res||query(L,R,lson);    if (R>m) res=res||query(L,R,rson);    return res; }void find(int p,int l,int r){    if (r-l<=1)    {        if (s1[r-1]==s2[r-1]) printf("%d\n",r-p+1);        else printf("%d\n",l-p+1);    }    else    {        int m=(l+r)/2;        if (query(p,m,1,n,1)) find(p,l,m-1);        else find(p,m,r);    }}void update(int p,int add,int l,int r,int rt){    if (l==r)    {        sum[rt]=add;        return;    }    int m=(l+r)>>1;    if (p<=m) update(p,add,lson);    else update(p,add,rson);    pushup(rt); }int main(){    int T,i,l1,l2,m,j;    scanf("%d",&T);    for (j=1;j<=T;j++)    {        scanf("%s",s1);        scanf("%s",s2);        clear(a);        clear(sum);        l1=strlen(s1);        l2=strlen(s2);        if (l1>l2) n=l1;        else n=l2;        n0=l1+l2-n;        for (i=1;i<=n;i++)        {            if (i<l1&&i<l2)                a[i]=s1[i-1]-s2[i-1];            else if (i>l1)                a[i]=-(s2[i-1]-'a'+1);            else a[i]=s1[i-1]-'a'+1;        }        k=0;        build(1,n,1);        printf("Case %d:\n",j);        scanf("%d",&m);        while (m--)        {            int x,y,z,add;            scanf("%d",&z);            if (z==2)            {                scanf("%d",&x);                if (x>=n0||s1[x]!=s2[x]) printf("%d\n",0);                else find(x+1,x+1,n0);            }            else            {                scanf("%d%d",&x,&y);                char c,ch;                scanf("%c%c",&c,&ch);                if (x==1)                {                    add=ch-s2[y];                    if (add^a[y+1]) update(y+1,add,1,n,1);                    s1[y]=ch;                }                else                {                    add=s1[y]-ch;                    if (add^a[y+1]) update(y+1,add,1,n,1);                     s2[y]=ch;                }                a[y+1]=add;            }        }    }    return 0;}


 

 

原创粉丝点击