hdu 4339 线段树+二分

题意是给你两个字符串    进行两种操作   1: 修改其中一个字符串里的某个字符2:   询问从i起两个字符串最多由多少个是相同的;

先说一下做之前的想法   ,我是看别人介绍树状数组是看到这道题的    本也想用树状数组做  ,没想上去    然后就改为线段树了   ,有很明显的点更新,区间查询,所以选择线段树;

思路:  每个节点num【】 存3个值       p1  p2  flash   flash表示当前节点两个字符串是不是一样的   若是则为1否则为0    p1 p2为当前两个字符串的字符(其实只有在最底端的节点  p1  p2才有意义)  题目给的是字符区间  而真正修改的是点    所以得先处理字符串加到线段树里也就是deal函数  (偷懒写在一个函数里果断超时了!!!)    然后对点来更新

对于查询 我是用的二分      开始j=最大长度     然后二分到底   虽然时间可能长点   但代码比较简单

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

#define LL(x) (x<<1)
#define RR(x) ((x<<1)|1)

char str1[1000010],str2[1000010];
struct node
{
    char p1,p2;
    int flash;
}num[4*1000000];
int max(int a,int b)
{
    return a>b?a:b;
}
int deal(int L,int R,int left,int right,int mark,int k,char str[])
{
    if(L==left&&right==R&&L==R)
    {
        if(k==1) num[mark].p1=str[L-1];
        else num[mark].p2=str[L-1];
        if(num[mark].p1==num[mark].p2) num[mark].flash=1;
        else num[mark].flash=0;
        return 0;
    }
    int mid=(L+R)/2;
    if(right<=mid)
    {
        deal(L,mid,left,right,LL(mark),k,str);
    }
    else if(left>mid)
    {
        deal(mid+1,R,left,right,RR(mark),k,str);
    }
    else
    {
        deal(L,mid,left,mid,LL(mark),k,str);
        deal(mid+1,R,mid+1,right,RR(mark),k,str);
    }
    if(num[LL(mark)].flash==0||num[RR(mark)].flash==0) num[mark].flash=0;
    else num[mark].flash=1;
    return 0;
}
int update(int L,int R,int dis,int mark,int k,char p)
{
    if(L==R&&L==dis)
    {
        if(k==1) num[mark].p1=p;
        else num[mark].p2=p;
        if(num[mark].p1==num[mark].p2) num[mark].flash=1;
        else num[mark].flash=0;
        return 0;
    }
    if(num[mark].flash==1)
    {
        num[LL(mark)].flash=num[RR(mark)].flash=num[mark].flash;
    }
    int mid=(L+R)/2;
    if(dis<=mid)
    {
        update(L,mid,dis,LL(mark),k,p);
    }
    else update(mid+1,R,dis,RR(mark),k,p);
    if(num[LL(mark)].flash==0||num[RR(mark)].flash==0)
    {
        num[mark].flash=0;
    }
    else  num[mark].flash=1;
    return 0;
}
int find(int L,int R ,int left,int right,int mark)
{
    if(num[mark].flash==1) return 1;
    if(left==L&&right==R) return -1;
    int mid=(L+R)/2;
    if(right<=mid)
    {
        return find(L,mid,left,right,LL(mark));
    }
    else if(left>mid)
    {
        return find(mid+1,R,left,right,RR(mark));
    }
    else
    {
        int t1=find(L,mid,left,mid,LL(mark));
        int t2=find(mid+1,R,mid+1,right,RR(mark));
        if(t1==-1||t2==-1) return -1;
        else return 1;
    }
}
int main()
{
    int len1,len2,T,i,d=1;
    scanf("%d",&T);
    while(T--)
    {
        printf("Case %d:\n",d++);
        scanf("%s%s",str1,str2);
        len1=strlen(str1);
        len2=strlen(str2);
        int L=1,R=max(len1,len2);
        memset(num,0,sizeof(num));
        deal(L,R,1,len1,1,1,str1);
        deal(L,R,1,len2,1,2,str2);
        int Q;
        scanf("%d",&Q);
        while(Q--)
        {
            int dis,x,k;
            char str[5];
            scanf("%d",&x);
            if(x==1)
            {
                scanf("%d%d%s",&k,&dis,str);
                dis++;
                update(L,R,dis,1,k,str[0]);
            }
            else
            {
                int left;
                scanf("%d",&left);
                int t=left;
                left++;
                int right=R;
                while(left<=right)
                {
                    int mid=(left+right)/2;
                    if(find(L,R,left,mid,1)==-1) right=mid-1;
                    else left=mid+1;
                }
                printf("%d\n",left-t-1);
            }
        }    

    }
    return 0;
}
时间: 2024-10-03 05:42:22

hdu 4339 线段树+二分的相关文章

HDU 4339 线段树区间合并

Query Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2573    Accepted Submission(s): 851 Problem Description You are given two strings s1[0..l1], s2[0..l2] and Q - number of queries.Your task

hdu 6070 线段树+二分

HDU - 6070 题意:提交了n次题目,每个题目都是最后一次提交的时候AC的,现在求一个区间,这个区间的AC率是最低的(只考虑这个区间内的题目,同样区间内最后交的一遍是AC的),求最低的AC率 思路:AC率=提交次数/题目数目,即区间长度/题目种类,siz[l,r]/(r-l+1)=p(siz[l,r]表示l r区间内的不同题目的个数,p表示AC率), 把式子做一下调整,siz[l,r]+p*l=p(r+1),二分p(0-1)用线段树维护siz[l,r]+l*p ,然后枚举r,每次更新,因为

HDU 3450 线段树+二分

点击打开链接 题意:给一个数字序列,问你长度大于2的且相邻两个数的差的绝对值不大于d的情况对9901取余 思路:看了根本不会,都没想到是线段树的题目,弱哭~~~,看了大牛们的题解,算是知道怎么回事了,对于当前的数A,那么以它为最后一个元素可以组成的情况是A-d到A+d的和,也可以这样想,A-d的已经组成了m种情况,那么在不影响小于d的情况下,可以直接将A放到A-d组成的左右序列中,那么直接加就可以了,而后更新A可以组成的情况,数据太大还需要离散化,然后二分找一下A-d和A+d的位置,数据可能没有

hdu 4614 线段树 二分

题意:有n个花瓶,每个花瓶中只能放一朵花. 两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放: 输出这次放的花的左右端点.如果能放但是放不完f朵输出n就好了 第二种是将区间[A,B]之间花瓶中的花清空.输出这次总共清理出了多少支花. 思路:第二种很明显可以用线段树实现,问题在第一种如何用线段树实现 用二分  和 线段树 来判断右端点的位置  这样就可以了  第一次操作就成了区间更新 并且查询左右端点 #include<cstdio> #include<

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

hdu 5592 ZYB&#39;s Premutation (线段树+二分查找)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=5592 Problem Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to  restore the premutation.Pair (i,j)(i<j) is considered as a reverse

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

HDU 4417 划分树+二分

题意:有n个数,m个询问(l,r,k),问在区间[l,r] 有多少个数小于等于k. 划分树--查找区间第k大的数.... 利用划分树的性质,二分查找在区间[l,r]小于等于k的个数. 如果在区间第 i 大的数tmp>k,则往下找,如果tmp<k,往上找. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #incl