hdu 4399

Description

You are given two strings s1[0..l1], s2[0..l2] and Q - number of queries.
Your task is to answer next queries:
  1) 1 a i c - you should set i-th character in a-th string to c;
  2) 2 i - you should output the greatest j such that for all k (i<=k and k<i+j) s1[k] equals s2[k].
 

Input

The first line contains T - number of test cases (T<=25).
Next T blocks contain each test.
The first line of test contains s1.
The second line of test contains s2.
The third line of test contains Q.
Next Q lines of test contain each query:
  1) 1 a i c (a is 1 or 2, 0<=i, i<length of a-th string, 'a'<=c, c<='z')
  2) 2 i (0<=i, i<l1, i<l2)
All characters in strings are from 'a'..'z' (lowercase latin letters).
Q <= 100000.
l1, l2 <= 1000000.
 

Output

For each test output "Case t:" in a single line, where t is number of test (numbered from 1 to T).
Then for each query "2 i" output in single line one integer j.
 

Sample Input

       
       
1 aaabba aabbaa 7 2 0 2 1 2 2 2 3 1 1 2 b 2 0 2 3
 

Sample Output

       
       
Case 1: 2 1 0 1 4 1
 


什么都不想说了。。。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1000010
//#define MIN(a,b) (a>b?b:a)//以后还是老老实实的写函数吧,表示被它坑了一上午。。。
using namespace std;
int len;

int MIN(int A,int B)
{
    return A<B?A:B;
}

struct node{
    int left,right,mid,val;
}tree[N<<2];

void build(int num,int s,int e)
{
    tree[num].left=s;
    tree[num].right=e;
    tree[num].val=len+1;
//    cout<<"tree["<<num<<"].left"<<tree[num].left<<tree[num].right<<endl;
    if(s<e)
    {
        tree[num].mid=(s+e)>>1;
        build(num<<1,s,tree[num].mid);
        build(num<<1|1,tree[num].mid+1,e);
    }
}

void change(int s,int pos,int va)
{
    if(tree[s].left==tree[s].right)
    {
        tree[s].val=va;
//        cout<<"tree["<<s<<"].acount"<<tree[s].val<<endl;
        return ;
    }
    if(pos<=tree[s].mid)
        change(s<<1,pos,va);
    else change(s<<1|1,pos,va);
    tree[s].val=MIN(tree[s<<1].val,tree[s<<1|1].val);
}

int finds(int num,int s,int e)
{
    if(s<=tree[num].left&&tree[num].right<=e)
    {
 //       cout<<"tree["<<s<<"].acount"<<tree[s].val<<endl;
        return tree[num].val;
    }
    if(e<=tree[num].mid)
        return finds(num<<1,s,e);
    else if(s>tree[num].mid)
        return finds(num<<1|1,s,e);
    else {
        return MIN(finds(num<<1,s,tree[num].mid),finds(num<<1|1,tree[num].mid+1,e));
    }
}

int main()
{
    char s[2][1000010],c;
    int T,Q,a,b,d;
    scanf("%d",&T);
    int k=1;
    while(T--)
    {
        scanf("%s",s[0]);
        scanf("%s",s[1]);
        len=MIN(strlen(s[0]),strlen(s[1]));
        build(1,1,len);
        for(int i=0;i<len;i++)
        {
            if(s[0][i]!=s[1][i])  //将不匹配的位标存入线段树里
                change(1,i+1,i+1);
        }
        printf("Case %d:\n",k++);
        scanf("%d",&Q);
        while(Q--)
        {
            scanf("%d",&a);
            if(a==2)
            {
                scanf("%d",&b);
                if(b>=len)
                    printf("0\n");
                else
                    printf("%d\n",finds(1,b+1,len)-b-1);
            }
            else
            {
                scanf("%d %d %c",&b,&d,&c);
                if(d>=len) continue;
                b--;
                if(s[b][d]==s[b^1][d]&&s[b][d]!=c)
                    change(1,d+1,d+1);
                if(s[b][d]!=s[b^1][d]&&s[b^1][d]==c)
                    change(1,d+1,len+1);
                s[b][d]=c;
            }
        }
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值