题目
序列a1,a2,...ap是好序列,
当且仅当p>=1且任意i∈[1,p),有
或
给定长为n(n<=1e5)的序列a1,...,an(1<=ai<=n),q(q<=2e5)次询问
每次询问给定k,l,r(1<=k<=n,1<=l<=r<=n),
询问区间[l,r]内的子序列中有多少个是好序列
答案对1e9+7取模
思路来源
比赛几分钟后才做出来,这种题做过无数次了,次次被卡
题解
一开始想着边转移,但是不行,需要有一个末态的概念
所以,需要按点转移,>=k记为状态1,
子序列矩阵可以0转移到0,1转移到1,0转移到1,1转移到0,
其中,前两种表示本次不取,后两种只能同时有一个存在,表示之前取的是0/1,本次取的是1/0
将k离线,建立线段树矩阵,在ai
注意到,c[0][0]和c[1][1]均有为空的一种方案,所以答案需要恒减2
最后几分钟就是这里没想清楚
代码
const int N=1e5+10,M=2e5+10,mod=1e9+7;
const int INF=0x3f3f3f3f;
int n,q,l,r,v,a[N],ans[M];
const static int MAXN = 2;
mat(int a, int b) : m(a), n(b) {
memset(c, 0, sizeof (c));
mat operator + (const mat& temp) {
for (int i = 0; i < m; i ++)
for (int j = 0; j < temp.n; j ++) {
for (int k = 0; k < n; k ++){
ans.c[i][j] = (ans.c[i][j] + 1ll * c[i][k] * temp.c[k][j] %mod)%mod;
node(int a,int b,int c):id(a),l(b),r(c){
dat[p]=dat[p<<1]+dat[p<<1|1];
void init(int p,int l,int r){
void build(int p,int l,int r){
void chg(int p,int l,int r,int pos){
if(pos<=mid)chg(p<<1,l,mid,pos);
else chg(p<<1|1,mid+1,r,pos);
mat ask(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return dat[p];
if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
return ask(p<<1,l,mid,ql,mid)+ask(p<<1|1,mid+1,r,mid+1,qr);
scanf("%d%d%d",&k,&l,&r);
f[k].push_back(node(i,l,r));
ans[id]=(1ll*y.c[0][0]+y.c[0][1]+y.c[1][0]+y.c[1][1])%mod;
ans[id]=(ans[id]+mod-2)%mod;