码迷,mamicode.com
首页 > 其他好文 > 详细

CF633H Fibonacci-ish II

时间:2021-04-07 11:15:58      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:friend   shu   ack   lse   code   const   ble   down   代码   

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;
}

CF633H Fibonacci-ish II

标签:friend   shu   ack   lse   code   const   ble   down   代码   

原文地址:https://www.cnblogs.com/Troverld/p/14620614.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!