首页 > 试题广场 >

研究red子序列的红

[编程题]研究red子序列的红
  • 热度指数:2881 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 512M,其他语言1024M
  • 算法知识视频讲解
\hspace{15pt}小红有两个长度为 n 的字符串 s,t ,仅包含小写字母,下标从 1 开始。
\hspace{15pt}她每次会进行一个操作,把 s_it_i 交换,你需要回答每一次交换后字符串 s 中的 \texttt{ 子序列和 t \texttt{ 子序列之差。
\hspace{15pt}每次询问不独立。

\hspace{15pt}子序列是指在一个序列中,通过删除某些元素(可以是零个或多个元素),而不改变其余元素的相对顺序所得到的序列。

输入描述:
\hspace{15pt}第一行两个整数 n,q \ (1\leqq n,q\leqq 2\times 10^5) 代表字符串长度和操作次数。
\hspace{15pt}第二行一个长度为 n 的字符串 s 。
\hspace{15pt}第三行一个长度为 n 的字符串 t 。
\hspace{15pt}此后 q 行,每行一个整数 x\ (1\leqq x\leqq n),表示每次交换的位置。


输出描述:
\hspace{15pt}对于每一次询问,在一行上输出一个整数,表示交换后字符串 s 中的 \texttt{ 子序列和 t 中 \texttt{ 的子序列之差。
示例1

输入

5 2
redar
adade
5
4

输出

1
2
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int q = in.nextInt();
        char[]s1 = in.next().toCharArray();
        char[]s2 = in.next().toCharArray();
        SegTree t1=SegTree.build(s1,0,n-1);
        SegTree t2=SegTree.build(s2,0,n-1);
        for (int i = 0; i < q; i++) {
            int x = in.nextInt();
            char c=s1[x-1];
            s1[x-1]=s2[x-1];
            s2[x-1]=c;
            t1.update(x-1,s1[x-1]);
            t2.update(x-1,s2[x-1]);
            System.out.println(t1.redcnt-t2.redcnt);
        }
    }
}
class SegTree{
    int l;
    int r;
    int rcnt;//r
    int ecnt;//e
    int dcnt;//d
    long recnt;//re
    long edcnt;//ed
    long redcnt;//red
    SegTree left;
    SegTree right;
    public void update(int k,char c){
        if(k<l||k>r)
            return;
        if(l==r&&l==k){
            rcnt=c=='r'?1:0;
            ecnt=c=='e'?1:0;
            dcnt=c=='d'?1:0;
            return;
        }
        int mid=(l+r)/2;
        if(k<=mid){
            left.update(k,c);
        }else{
            right.update(k,c);
        }
        mergeSub();
    }
    public void mergeSub(){
        rcnt=left.rcnt+right.rcnt;
        ecnt=left.ecnt+right.ecnt;
        dcnt=left.dcnt+right.dcnt;
        recnt=left.recnt+right.recnt+left.rcnt*right.ecnt;
        edcnt=left.edcnt+right.edcnt+left.ecnt*right.dcnt;
        redcnt=left.redcnt+right.redcnt+left.rcnt*right.edcnt+left.recnt*right.dcnt;
    }

    public static SegTree build(char[]s,int l,int r)
    {
        SegTree t=new SegTree();
        t.l=l;
        t.r=r;
        if(l==r)
        {
            t.rcnt=s[l]=='r'?1:0;
            t.ecnt=s[l]=='e'?1:0;
            t.dcnt=s[l]=='d'?1:0;
            t.recnt=t.edcnt=t.redcnt=0;
            return t;
        }
        int mid=(l+r)/2;
        t.left=build(s,l,mid);
        t.right=build(s,mid+1,r);
        t.mergeSub();
        return t;
    }


}
看了一眼,没有人用Java写写线段树,我在这里写一个,希望对大家有帮助
本题注意点:
1)下次交换是再前一个交换的基础上交换的
2)结果可能大于int,要用long
发表于 2025-03-26 21:14:04 回复(0)