[权值线段树]JZOJ 4417 神奇的字符串

Description

 

Input

Output

 

Sample Input

9 5 6 4 3
101
11
Query 0
Query 1
Query 2
Query 3
Query 4
Query 5
Query 6
Query 7
Query 8
Change 1
Query 3

Sample Output

0
3
0
2
2
0
3
0
3
1
 

Data Constraint

分析

这题有很多表达没看懂,例如(N,A)=1什么的(毕竟我比较菜)

但是不影响写题(因为我不会写啊哈哈哈)

我们将c分成两类,相当于给c排了序,即0的部分下标就是0~p-1,1的部分下标就是p~n-1(也就是把题目所说式子转化为下标,数组元素才储存值)

然后我们发现这个排完序的数组是有序的(废话),通过思考(交流学习)可以发现,它们所对应的原下标也是有序的

x=x1-a*i(不考虑模)

那么我们就可以将s中每一个值都带进去得到一个开头区间,给区间加一

问题转化为询问一个点在多少个区间内出现,且区间可以改变

权值线段树可以解决这样的问题

#include <iostream>
#include <cstdio>
using namespace std;
const int N=1e5+10;
struct Seg {
    int l,r,cnt,lz;
}s[10000010];
int cnt;
char c[N];
int n,a,b,p,m,q;

void Calc(int i,int &l,int &r) {
    int x=c[i]-'0';
    if (x) l=0,r=p-1; else l=p,r=n-1;
    l=((l-a*i)%n+n)%n;r=((r-a*i)%n+n)%n;
}

void New(int x) {
    if (!s[x].l) s[x].l=++cnt;
    if (!s[x].r) s[x].r=++cnt;
}

void Pushdown(int x) {
    s[s[x].l].lz+=s[x].lz;s[s[x].l].cnt+=s[x].lz;
    s[s[x].r].lz+=s[x].lz;s[s[x].r].cnt+=s[x].lz;
    s[x].lz=0;
}

void Change(int x,int l,int r,int ll,int rr,int val) {
    if (ll<=l&&r<=rr) {
        s[x].cnt+=val;s[x].lz+=val;
        return;
    }
    New(x);Pushdown(x);
    int mid=l+r>>1;
    if (ll<=mid) Change(s[x].l,l,mid,ll,rr,val);
    if (mid<rr) Change(s[x].r,mid+1,r,ll,rr,val);
}

int Query(int x,int l,int r,int k) {
    if (l==r&&l==k) return s[x].cnt;
    New(x);Pushdown(x);
    int mid=l+r>>1;
    if (k<=mid) return Query(s[x].l,l,mid,k);
    else return Query(s[x].r,mid+1,r,k);
}

void Change(int l,int r,int val) {
    if (l<=r) Change(0,0,n-1,l,r,val);
    else Change(0,0,n-1,l,n-1,val),Change(0,0,n-1,0,r,val);
}

int main() {
    scanf("%d%d%d%d%d",&n,&a,&b,&p,&m);
    scanf("%s",c);
    for (int i=0;i<m;i++) {
        int l,r;
        Calc(i,l,r);
        Change(l,r,1);
    }
    scanf("%d",&q);
    while (q--) {
        char w[10];int x;
        scanf("%s%d",w,&x);
        if (w[0]=='Q') printf("%d\n",Query(0,0,n-1,(a*x+b)%n));
        else {
            int l,r;
            Calc(x,l,r);
            Change(l,r,-1);
            c[x]=!(c[x]-'0')+'0';
            Calc(x,l,r);
            Change(l,r,1);
        }
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/mastervan/p/10290402.html