hdu6078 二维树状数组

Wavel Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 986    Accepted Submission(s): 492


 

Problem Description

Have you ever seen the wave? It's a wonderful view of nature. Little Q is attracted to such wonderful thing, he even likes everything that looks like wave. Formally, he defines a sequence a1,a2,...,an as ''wavel'' if and only if a1<a2>a3<a4>a5<a6...



Picture from Wikimedia Commons



Now given two sequences a1,a2,...,an and b1,b2,...,bm, Little Q wants to find two sequences f1,f2,...,fk(1≤fi≤n,fi<fi+1) and g1,g2,...,gk(1≤gi≤m,gi<gi+1), where afi=bgi always holds and sequence af1,af2,...,afk is ''wavel''.

Moreover, Little Q is wondering how many such two sequences f and g he can find. Please write a program to help him figure out the answer.

Input

The first line of the input contains an integer T(1≤T≤15), denoting the number of test cases.

In each test case, there are 2 integers n,m(1≤n,m≤2000) in the first line, denoting the length of a and b.

In the next line, there are n integers a1,a2,...,an(1≤ai≤2000), denoting the sequence a.

Then in the next line, there are m integers b1,b2,...,bm(1≤bi≤2000), denoting the sequence b.

Output

For each test case, print a single line containing an integer, denoting the answer. Since the answer may be very large, please print the answer modulo 998244353.

Sample Input

 

1

3 5

1 5 3

4 1 1 5 3

Sample Output

10

Hint

简单的二维bits,对于每一位可以选的值,在二维树状数组中找到和更新满足的值,维护两个二维树状数组,一个是最后一个值是上升的,一个是最后一个值是下降的

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int maxn = 1e5+9;


int a[maxn],b[maxn];
int n,m;
ll bit1[2009][2009],bit2[2009][2009];

ll Query1(int j,int x){
    ll ans=0;
    while(x){
        ans=(ans+bit1[j][x])%mod;
        x-=(x&-x);
    }
    return ans;
}

ll query1(int j,int x){
    ll ans=0;
    while(j){
        ans=(ans+Query1(j,x))%mod;
        j-=(j&-j);
    }
    return ans;
}

ll Query2(int j,int x){
    ll ans=0;
    while(x){
        ans=(ans+bit2[j][x])%mod;
        x-=(x&-x);
    }
    return ans;
}

ll query2(int j,int x){
    ll ans=0;
    while(j){
        ans=(ans+Query2(j,x))%mod;
        j-=(j&-j);
    }
    return ans;
}

void Add1(int j,int x,ll y){
    while(x<=2000){
        bit1[j][x]=(bit1[j][x]+y)%mod;
        x+=(x&-x);
    }
}

void add1(int j,int x,ll y){
    while(j<=m){
        Add1(j,x,y);
        j+=(j&-j);
    }
}

void Add2(int j,int x,ll y){
    while(x<=2000){
        bit2[j][x]=(bit2[j][x]+y)%mod;
        x+=(x&-x);
    }
}

void add2(int j,int x,ll y){
    while(j<=m){
        Add2(j,x,y);
        j+=(j&-j);
    }
}

int main(){
    int t;scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<=2000;i++){
            for(int j=0;j<=2000;j++){
                bit1[i][j]=bit2[i][j]=0;
            }
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d",&b[i]);
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(a[i]==b[j]){
                    ans=(ans+1)%mod;
                    ll x=query1(j,a[i]-1);
                    ll y=(query2(j,2000)-query2(j,a[i])+mod)%mod;
                    ans=(ans+x+y)%mod;
                    add1(j,a[i],y+1);
                    add2(j,a[i],x);
                }
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值