CF 610E. Alphabet Permutations

题目:http://codeforces.com/problemset/problem/610/E

如果存在c1,c2在原串相邻且在询问串中c1在c2前面的话,把它们在原串出现次数加起来记作sum,那么n-sum就是答案。

维护一棵线段树,线段树的每个节点存一个k^2的矩阵。

然后修改的话就在线段树上区间修改。。(标记下传的时候要注意不要越界TAT。。。

然后询问的话就k^2搞一下需要被减掉的字符对就好了。。

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define low(x) (x&(-x))
#define maxn 12
#define ll long long
using namespace std;
int n,m,K,ans;
char s[200500],s2[maxn];
int a[maxn][maxn];
struct data{int mat[maxn][maxn],l,r,tag;
}t[200500*4];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void combine(data &a,data b,data c){
    a.l=b.l; a.r=c.r;
    rep(i,0,K-1) rep(j,0,K-1) a.mat[i][j]=b.mat[i][j]+c.mat[i][j];
    a.mat[b.r][c.l]++;
    a.tag=-1;
}
void build(int i,int l,int r){
    int mid=(l+r)/2;
    if (l==r){
        t[i].tag=-1; t[i].l=t[i].r=s[l]-'a';
        clr(t[i].mat,0);
        return ;
    }
    build(i*2,l,mid); build(i*2+1,mid+1,r);
    combine(t[i],t[i*2],t[i*2+1]);
}
void ps(int i,int l,int r){
    if (t[i].tag!=-1){
        t[i].l=t[i].r=t[i].tag;
        clr(t[i].mat,0);
        t[i].mat[t[i].tag][t[i].tag]=r-l;
        if (l!=r) t[i*2].tag=t[i*2+1].tag=t[i].tag;
        t[i].tag=-1;
    }
}
void change(int i,int l,int r,int tl,int tr,int val){
    ps(i,l,r);
    int mid=(l+r)/2;
    if (l==tl&&r==tr){
        t[i].tag=val;
        ps(i,l,r); 
        return ;
    }
    if (tr<=mid) {
        change(i*2,l,mid,tl,tr,val);
        ps(i*2+1,mid+1,r);
    }
    else if (tl>mid){
        change(i*2+1,mid+1,r,tl,tr,val);
        ps(i*2,l,mid);
    }
    else {
        change(i*2,l,mid,tl,mid,val);
        change(i*2+1,mid+1,r,mid+1,tr,val);
    }
    combine(t[i],t[i*2],t[i*2+1]);
}
int main(){
    n=read(); m=read(); K=read();
    scanf("%s",s); 
    build(1,0,n-1);
    rep(i,1,m){
        int op=read();
        if (op==1){
            int l=read()-1,r=read()-1; scanf("%s",s2);
            int now=s2[0]-'a';
            change(1,0,n-1,l,r,now);
        }
        else {
            ans=n;
            scanf("%s",s2);
            rep(j,0,K-1) rep(k,0,K-1) a[j][k]=0;
            rep(j,0,K-1) rep(k,j+1,K-1) a[s2[j]-'a'][s2[k]-'a']=1;
            rep(j,0,K-1) rep(k,0,K-1) ans-=t[1].mat[j][k]*a[j][k]; 
            printf("%d\n",ans);
         }
    }
    return 0;
}

 

posted on 2015-12-29 18:50  ctlchild  阅读(295)  评论(0编辑  收藏  举报

导航