ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF633H Fibonacci-ish II

2021-04-06 10:33:16  阅读:177  来源: 互联网

标签:seg Matrix int lim void register II CF633H ish


VIII.CF633H Fibonacci-ish II

强烈谴责卡常屑题(

莫队。于是要支持插入数、查询与斐波那契数列的点积和。

离散化后就直接在线段树上处理。于是变成单点插入/删除(这个很 easy)以及后缀斐波那契数列前移/后移。

直接上矩阵维护。但是会TLE(因为常数是 \(2^3\))。预处理出斐波那契数列转移矩阵的正负 \(n\) 次幂,就能将转移优化到 \(2^2\),实际效果还要更好(时间是原来的 \(1/4\))。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,mod,a[30100],buc[30100],res[30100],m,lim;
const int BBB=240;
struct Matrix{
	int a[2][2];
	int*operator[](const int &x){return a[x];}
	Matrix(){memset(a,0,sizeof(a));}
	friend Matrix operator*(register Matrix&u,register Matrix&v){
		Matrix w;
		for(register int i=0;i<2;i++)for(register int j=0;j<2;w[i][j++]%=mod)for(register int k=0;k<2;k++)w[i][j]+=u[i][k]*v[k][j];
		return w;
	}
	void print()const{for(register int i=0;i<2;i++){for(register int j=0;j<2;j++)printf("%d ",a[i][j]);puts("");}}
}F,G,I,f[30100],g[30100];
Matrix ksm(register Matrix x,register int y){register Matrix z=I;for(;y;y>>=1,x=x*x)if(y&1)z=z*x;return z;}
vector<int>v;
struct SegTree{int s[2],sz,tag;}seg[120100];
inline void MUL(register int *x,register Matrix M){
	register int z[2];z[0]=z[1]=0;
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)z[j]+=x[i]*M[i][j];
	x[0]=z[0]%mod,x[1]=z[1]%mod;
}
#define lson x<<1
#define rson x<<1|1
void SUM(int&x,int&y,int&z){x=y+z;if(x>=mod)x-=mod;}
inline void MUL(register int x,register int y){MUL(seg[x].s,y>=0?f[y]:g[-y]),seg[x].tag+=y;}
inline void pushdown(register int x){if(seg[x].tag)MUL(lson,seg[x].tag),MUL(rson,seg[x].tag),seg[x].tag=0;}
inline void pushup(register int x){for(register int i=0;i<2;i++)SUM(seg[x].s[i],seg[lson].s[i],seg[rson].s[i]);seg[x].sz=seg[lson].sz+seg[rson].sz;}
inline void turnon(register int x,register int l,register int r,register int P,register int val){
	if(l==r){seg[x].s[0]=0,seg[x].s[1]=v[P-1],MUL(x,val),seg[x].sz=1;return;}
	register int mid=(l+r)>>1;pushdown(x);if(P<=mid)turnon(lson,l,mid,P,val);else turnon(rson,mid+1,r,P,val);pushup(x);
}
inline void turnoff(register int x,register int l,register int r,register int P){
	if(l==r){seg[x].s[0]=seg[x].s[1]=seg[x].sz=0;return;}
	register int mid=(l+r)>>1;pushdown(x);if(P<=mid)turnoff(lson,l,mid,P);else turnoff(rson,mid+1,r,P);pushup(x);
}
inline int querysz(register int x,register int l,register int r,register int P){
	if(l>P)return 0;if(r<=P)return seg[x].sz;
	register int mid=(l+r)>>1;return querysz(lson,l,mid,P)+querysz(rson,mid+1,r,P);
}
inline void modifymatrix(register int x,register int l,register int r,register int P,register int tp){
	if(r<P)return;if(l>=P){MUL(x,tp);return;}
	register int mid=(l+r)>>1;pushdown(x),modifymatrix(lson,l,mid,P,tp),modifymatrix(rson,mid+1,r,P,tp),pushup(x);
}
struct QUERY{int l,r,id;friend bool operator<(const QUERY&u,const QUERY&v){if(u.l/BBB!=v.l/BBB)return u.l<v.l;return(u.l/BBB)&1?u.r<v.r:u.r>v.r;}}q[30100];
inline void Push(register int x){if(!buc[a[x]]++)turnon(1,1,lim,a[x],querysz(1,1,lim,a[x])),modifymatrix(1,1,lim,a[x],1);}
inline void Pop(register int x){if(!--buc[a[x]])turnoff(1,1,lim,a[x]),modifymatrix(1,1,lim,a[x],-1);}
char buf[1<<20],*ss=buf,*tt=buf;
#define gc() (tt==ss&&(tt=(ss=buf)+fread(buf,1,1<<20,stdin),ss==tt)?EOF:*ss++)
inline void read(register int &x){x=0;register char c=gc();while(c>'9'||c<'0')c=gc();while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=gc();}
inline void print(register int x){if(x<=9)putchar('0'+x);else print(x/10),putchar('0'+x%10);}
int main(){
	read(n),read(mod);
	F[0][0]=0,F[0][1]=1,F[1][0]=1,F[1][1]=1;
	G[0][1]=1,G[0][0]=mod-1,G[1][0]=1,G[1][1]=0;
	I[0][0]=1,I[1][1]=1,I[1][0]=0,I[0][1]=0;
	f[0]=g[0]=I;for(int i=1;i<=n;i++)f[i]=f[i-1]*F,g[i]=g[i-1]*G;
	for(register int i=1;i<=n;i++)read(a[i]),v.push_back(a[i]);
	sort(v.begin(),v.end()),v.resize(lim=unique(v.begin(),v.end())-v.begin());
	for(register int i=1;i<=n;i++)a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
	for(int i=0;i<v.size();i++)v[i]%=mod;
	read(m);
	for(register int i=1;i<=m;i++)read(q[i].l),read(q[i].r),q[i].id=i;
	sort(q+1,q+m+1);
	register int L=1,R=0;
	for(register int i=1;i<=m;i++){
		while(L>q[i].l)Push(--L);
		while(R<q[i].r)Push(++R);
		while(L<q[i].l)Pop(L++);
		while(R>q[i].r)Pop(R--);
//		iterate(1,1,lim);puts("");
		res[q[i].id]=seg[1].s[0];
	}
	for(int i=1;i<=m;i++)print(res[i]),putchar('\n');
	return 0;
}

标签:seg,Matrix,int,lim,void,register,II,CF633H,ish
来源: https://www.cnblogs.com/Troverld/p/14620614.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有