[ DP 莫队 ]「2017 山东一轮集训 Day6」LOJ#6074 子序列

11 篇文章 0 订阅

题解

#include<bits/stdc++.h>
using namespace std;
const int SZ=1<<25; 
char nc() {
    static char buf[SZ],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,SZ,stdin),p1==p2)?EOF:*p1++;
}
void Read(int& x) {
    char c=nc();
    for(;c<'0'||c>'9';c=nc());
    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
int Read(int* a) {
    char c=nc();int len=0;
    for(;c<'a'||c>'z';c=nc());
    for(;c>='a'&&c<='z';c=nc()) a[++len]=c-'a'+1;
    return len;
}
typedef long long ll;
const int N=100010;
const int P=1000000007;
struct Node {
    int l,r,id;
}c[N];
int k,n,m;
int a[N];
int S,b[N];
ll Res,cnt[10][10];
int Ans[N];
char s[N];
bool Cmp(Node x,Node y) {
    return b[x.l]<b[y.l]||(b[x.l]==b[y.l]&&(b[x.l]&1?x.r<y.r:x.r>y.r));
}
void Add(ll& x,int y) {
    x=(x+y)%P;
}
void Add_r(int x) {
    for(int i=1;i<=9;i++) {
        int y=cnt[i][0]-cnt[i][x]+(i==x);
        Res+=y;Add(cnt[i][x],y);Add(cnt[i][0],y);Add(cnt[0][x],y);
    }
    Res%=P;
}
void Add_l(int x) {
    for(int i=1;i<=9;i++) {
        int y=cnt[0][i]-cnt[x][i]+(i==x);
        Res+=y;Add(cnt[x][i],y);Add(cnt[0][i],y);Add(cnt[x][0],y);
    }
    Res%=P;
}
void Del_r(int x) {
    for(int i=1;i<=9;i++) {
        int y=-cnt[i][0]+cnt[i][x]-(i==x);
        Res+=y;Add(cnt[i][x],y);Add(cnt[i][0],y);Add(cnt[0][x],y);
    }
    Res%=P;
}
void Del_l(int x) {
    for(int i=1;i<=9;i++) {
        int y=-cnt[0][i]+cnt[x][i]-(i==x);
        Res+=y;Add(cnt[x][i],y);Add(cnt[0][i],y);Add(cnt[x][0],y);
    }
    Res%=P;
}
int main() {
    n=Read(a);S=sqrt(n);
    for(int i=1;i<=n;i++) b[i]=(i-1)/S+1;
    Read(m);
    for(int i=1;i<=m;i++) Read(c[i].l),Read(c[i].r),c[i].id=i;
    sort(c+1,c+m+1,Cmp);
    int L=1,R=0;
    for(int i=1;i<=m;i++) {
        while(R<c[i].r) Add_r(a[++R]);
        while(R>c[i].r) Del_r(a[R--]);
        while(L>c[i].l) Add_l(a[--L]);
        while(L<c[i].l) Del_l(a[L++]);
        Ans[c[i].id]=Res;
    }
    for(int i=1;i<=m;i++) printf("%d\n",(Ans[i]+P)%P);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值