其他分享
首页 > 其他分享> > CF633H Fibonacci-ish II 莫队 线段树 矩阵

CF633H Fibonacci-ish II 莫队 线段树 矩阵

作者:互联网

CF633H Fibonacci-ish II

题意很简明 同时给人以不可做感。

直接暴力大概是\(n^2log\)的 优化一下提前排好序 从小到大枚举数字再枚举询问可以完成\(n^2\)

经过精细的优化竟然可以过了这个题,可能是出题人没有刻意卡或者根本没想到(赛后hack肯定是有的。

直接得到一个区间谁也做不了,考虑线段树维护区间 发现也不太能做。

容易考虑莫队得到每个区间 在加入一个数字的时候 若这个数字不是第一次加入

带来的影响是比它小的数字不变 后面的统一斐波那契数列向后推一项。

后者这个操作可以使用矩阵来做多乘以一个矩阵就能完成区间修改。

删除类似要乘以一个逆矩阵。注意细节。

关于初始化标记的矩阵最好的初始化为 1001这是单位矩阵,比 0000 的意义更明确。
在单点修改x的时候查找x的排名省掉一个树状数组或者说线段树上的一次查询。

pushdown的时候卡卡常不用改变就不改。

最后一个较为关键的是 莫队的排序 由于莫队指针移动一次的复杂度不是O(1) 所以进行奇偶性优化就很关键,可以省掉一大波常数。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define a(x) t[x].a
#define sum(x) t[x].sum
#define b(x) t[x].b
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
const int MAXN=30010;
int n,m,Q,cnt,S,cc;
int gg[2][2],kk[2][2];
int a[MAXN],B[MAXN],c[MAXN],ans[MAXN],w[MAXN],g[MAXN],f[MAXN],v[MAXN];
inline void 
struct wy
{
	int a,b,sum;
	int c[2][2];
}t[MAXN<<2];
struct jl
{
	int l,r;
	int id;
}s[MAXN];
inline int cmp(jl a,jl b){return B[a.l]==B[b.l]?((B[a.l]&1)?a.r>b.r:a.r<b.r):a.l<b.l;}
inline void discrete()
{
	sort(c+1,c+1+n);
	rep(1,n,i)if(i==1||c[i]!=c[i-1])c[++cnt]=c[i];
	rep(1,n,i)a[i]=lower_bound(c+1,c+1+cnt,a[i])-c;
	rep(1,cnt,i)c[i]%=m;
}
inline void build(int p,int l,int r)
{
	t[p].c[0][0]=t[p].c[1][1]=1;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
}
inline void pushdown(int p)
{
	if(t[p].c[0][0]==1&&t[p].c[1][1]==1&&t[p].c[1][0]==0&&t[p].c[0][1]==0)return;
	
	if(sum(p<<1))
	{
		int ww=(a(p<<1)*t[p].c[0][0]+b(p<<1)*t[p].c[1][0])%m;
		b(p<<1)=(a(p<<1)*t[p].c[0][1]+b(p<<1)*t[p].c[1][1])%m;
		a(p<<1)=ww;
	
	if(t[p<<1].c[0][0]==1&&t[p<<1].c[1][1]==1&&t[p<<1].c[1][0]==0&&t[p<<1].c[0][1]==0)
		rep(0,1,i)rep(0,1,j)t[p<<1].c[i][j]=t[p].c[i][j];
	else
	{
		rep(0,1,i)rep(0,1,j)kk[i][j]=t[p<<1].c[i][j],t[p<<1].c[i][j]=0;
		rep(0,1,i)rep(0,1,j)rep(0,1,k)t[p<<1].c[i][j]=(t[p<<1].c[i][j]+kk[i][k]*t[p].c[k][j]);
		t[p<<1].c[0][0]%=m;
		t[p<<1].c[1][1]%=m;
		t[p<<1].c[1][0]%=m;t[p<<1].c[0][1]%=m;
	}
	}
	if(sum(p<<1|1))
	{
		int ww=(a(p<<1|1)*t[p].c[0][0]+b(p<<1|1)*t[p].c[1][0])%m;
		b(p<<1|1)=(a(p<<1|1)*t[p].c[0][1]+b(p<<1|1)*t[p].c[1][1])%m;
		a(p<<1|1)=ww;
	
	if(t[p<<1|1].c[0][0]==1&&t[p<<1|1].c[1][1]==1&&t[p<<1|1].c[1][0]==0&&t[p<<1|1].c[0][1]==0)
		rep(0,1,i)rep(0,1,j)t[p<<1|1].c[i][j]=t[p].c[i][j];
	else
	{
		rep(0,1,i)rep(0,1,j)kk[i][j]=t[p<<1|1].c[i][j],t[p<<1|1].c[i][j]=0;
		rep(0,1,i)rep(0,1,j)rep(0,1,k)t[p<<1|1].c[i][j]=(t[p<<1|1].c[i][j]+kk[i][k]*t[p].c[k][j]);
		t[p<<1|1].c[0][0]%=m;t[p<<1|1].c[1][1]%=m;t[p<<1|1].c[1][0]%=m;t[p<<1|1].c[0][1]%=m;
	}
	}
	t[p].c[0][0]=t[p].c[1][1]=1;t[p].c[1][0]=t[p].c[0][1]=0;
}
inline void pushup(int p)
{
	a(p)=(a(p<<1)+a(p<<1|1))%m;
	b(p)=(b(p<<1)+b(p<<1|1))%m;
	sum(p)=sum(p<<1)+sum(p<<1|1);
}
inline void change(int p,int l,int r,int x)
{
	if(l==r)
	{
		++sum(p);
		a(p)=c[x]*f[cc]%m;
		b(p)=c[x]*f[cc-1]%m;
		return;
	}
	pushdown(p);
	int mid=(l+r)>>1;
	if(x<=mid)change(p<<1,l,mid,x);
	else cc+=sum(p<<1),change(p<<1|1,mid+1,r,x);
	pushup(p);
}
inline void change1(int p,int l,int r,int x)
{
	if(l==r)
	{
		a(p)=b(p)=0;
		--sum(p);
		return;
	}
	pushdown(p);
	int mid=(l+r)>>1;
	if(x<=mid)change1(p<<1,l,mid,x);
	else change1(p<<1|1,mid+1,r,x);
	pushup(p);
}
inline void modify(int p)
{
	int ww=(a(p)*gg[0][0]+b(p)*gg[1][0])%m;
	b(p)=(a(p)*gg[0][1]+b(p)*gg[1][1])%m;
	a(p)=ww;
	
	rep(0,1,i)rep(0,1,j)kk[i][j]=t[p].c[i][j],t[p].c[i][j]=0;
	rep(0,1,i)rep(0,1,j)rep(0,1,k)t[p].c[i][j]=(t[p].c[i][j]+kk[i][k]*gg[k][j])%m;
}
inline void modify(int p,int l,int r,int L)
{
	if(l>=L)
	{
		if(sum(p))
		{
			gg[0][0]=1;gg[0][1]=1;
			gg[1][0]=1;gg[1][1]=0;
			modify(p);
		}
		return;
	}
	pushdown(p);
	int mid=(l+r)>>1;
	if(L<=mid)modify(p<<1,l,mid,L);
	modify(p<<1|1,mid+1,r,L);
	pushup(p);
}
inline void modify1(int p,int l,int r,int L)
{
	if(l>=L)
	{
		if(sum(p))
		{
			gg[0][0]=0;gg[0][1]=1;
			gg[1][0]=1;gg[1][1]=m-1;
			modify(p);
		}
		return;
	}
	pushdown(p);
	int mid=(l+r)>>1;
	if(L<=mid)modify1(p<<1,l,mid,L);
	modify1(p<<1|1,mid+1,r,L);
	pushup(p);
}
inline void add(int x)
{
	if(v[a[x]]==0)
	{
		cc=1;change(1,1,cnt,a[x]);
		if(a[x]+1<=cnt)modify(1,1,cnt,a[x]+1);
	}
	++v[a[x]];
}
inline void del(int x)
{
	if(v[a[x]]==1)
	{
		change1(1,1,cnt,a[x]);
		if(a[x]+1<=cnt)modify1(1,1,cnt,a[x]+1);
	}
	--v[a[x]];
}
int main()
{
	freopen("1.in","r",stdin);
	n=read();m=read();
	rep(1,n,i)c[i]=a[i]=read();
	Q=read();
	rep(1,Q,i)s[i].l=read(),s[i].r=read(),s[i].id=i;
	
	discrete();
	f[1]=1;
	rep(2,n,i)f[i]=(f[i-1]+f[i-2])%m;
	build(1,1,cnt);
	
	S=(int)sqrt(n*1.0)+1;
	rep(1,n,i)B[i]=(i-1)/S;
	sort(s+1,s+1+Q,cmp);
	
	int L=1,R=0;
	rep(1,Q,i)
	{
		while(R<s[i].r)add(++R);
		while(s[i].l<L)add(--L);
		while(R>s[i].r)del(R),--R;
		while(L<s[i].l)del(L),++L;
		ans[s[i].id]=a(1);
	}
	
	rep(1,Q,i)printf("%d\n",ans[i]);
	return 0;
}

标签:gg,sum,long,II,CF633H,ish,include,莫队,define
来源: https://www.cnblogs.com/chdy/p/16638009.html