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

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

时间:2022-08-30 07:44:22浏览次数:87  
标签:gg 矩阵 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,矩阵,long,II,CF633H,ish,include,莫队,define
From: https://www.cnblogs.com/chdy/p/16638009.html

相关文章

  • Apache与IIS的优劣对比
    对于中小企业来说建立自己的网站,对外展示自己的页面是最平常不过的事情了。目前最流行的建立WWW服务工具就要属Apache与IIS了。那么他们之间都有什么区别呢?到底哪个工具才......
  • 「翻译」SAP制造集成和智能(SAP MII)
    SAP制造集成和智能(SAPMII)  集成和连接是成功的工业4.0计划的关键。SAPManufacturingIntegrationandIntelligence(SAPMII)是集成各种应用程序、设备和传感器并将......
  • 「翻译」SAP MII(SAP制造集成和智能)-灵活且可扩展
    SAPMII(SAP制造集成和智能)-灵活且可扩展    通过SAPMII,SAP提供了一个基于Web的、标准化和灵活的IT平台,用于垂直集成到生产中。这将面向流程的制造单元的生产......
  • VisualStudio启动项目提示“[xxxx] iisexpress.exe”已退出
    一、在通过VisualStudio直接启动项目时,iisexpress.exe直接退出1.程序“[6068]iisexpress.exe:程序跟踪”已退出,返回值为0(0x0)。2.程序“[6068]iisexpress.exe“已......
  • 【leetcode】81. 搜索旋转排序数组 II
    原题地址:https://leetcode.cn/problems/search-in-rotated-sorted-array-ii/用循环遍历数组肯定能轻松找到target但要尽可能减少操作步骤,一般跟顺序有关的都是用二分,关键......
  • leetcode 227. Basic Calculator II 基本计算器 II(中等)
    一、题目大意给你一个字符串表达式s,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。你可以假设给定的表达式总是有效的。所有中间结果将在[-23......
  • 多重背包问题 II
    多重背包问题II(水题但有注意点)二进制优化的多重背包问题(主要注意的是二进制优化后的数组的大小问题)AC代码#include<cstdio>#include<iostream>#include<algorit......
  • Vite配置如何优雅的code spliiting代码分割
    Vite如何配置分割代码什么是代码分割/codespliiting前端生态rollup和webpack都有的概念。如果把所有代码都打包到一起,可能最终的代码非常大。从而影响加载时间。而......
  • 137. 只出现一次的数字 II
     难度中等908收藏分享切换为英文接收动态反馈给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次。请你找出并返回那个只出现了一次......
  • LeetCode 2186. Minimum Number of Steps to Make Two Strings Anagram II
    原题链接在这里:https://leetcode.com/problems/minimum-number-of-steps-to-make-two-strings-anagram-ii/题目:Youaregiventwostrings s and t.Inonestep,you......