ICode9

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

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

2022-08-30 08:01:25  阅读:153  来源: 互联网

标签:gg sum long II CF633H ish include 莫队 define


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

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

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

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

ICode9版权所有