题目

斐波那契数列\(f\),\(f\_1=f\_2=1,\ f\_n=f\_{n-1}+f\_{n-2}\ (n>2)\)。

给定长度为\(n\ (n\le 30000)\)的数列\(a\),\(q\)次询问,每次将\(a\)的区间\([l,r]\)排序去重,设得到\(k\)个数:

\[\begin{align}
ans=\sum _{i=1}^k f_ia_i
\end{align}
\]

分析

会写莫队啦!会写莫队啦!会写莫队啦!

莫队算法的排序以左端点所在块和右端点的大小为关键字。

询问区间,\(n\le 30000)\),可以离线,莫队解决。关键在于如何添加或删除一个数。我们列出式子之后发现,每次操作其实可以等价于两个操作:

  • 添加或删除一个数
  • 把一段区间的数的所有\(f\)向前或向后移

    这里的排序去重令我们想到可以用权值线段树处理一个数前面有多少个数,所以添加删除可以\(O(logn)\)解决。现在考虑如何处理移动问题。

    我们对于权值线段树的每个点记录两个值,\((x,y)\),分别表示当前这个点区间内的答案,以及整个区间向后移动一位后的答案。我在这里的做法是用一个标记记录每个区间向右移动的次数(向左为负),然后\(pushdown\)的时候用矩阵快速幂加一下即可。右移矩阵为:

\[\begin{pmatrix}
0 & 1 \\ 1 & 1 \\
\end{pmatrix}
\]

左移矩阵为右移矩阵的逆矩阵,即:

\[\begin{pmatrix}
-1 & 1 \\ 1 & 0 \\
\end{pmatrix}
\]

时间复杂度:\(O(n\sqrt n logn)\)

这里最重要的思想是用离散化+权值线段树处理排序去重区间操作的问题。

代码

函数记得return返回值。

还有就是每次要把gs清空,也可以用标记实现。

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long giant;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=3e4+10;
int n,a[maxn],qn;
giant q;
struct ques {
int s,t,id;
bool operator < (const ques a) const {
int sk=s/qn,ak=a.s/qn;
return sk==ak?t<a.t:sk<ak;
}
} b[maxn];
int gs[maxn],tp,tic[maxn<<2],tim=0,tg[maxn];
giant f[maxn],c[maxn];
struct node {
giant a,b;
int mv,g;
void clear() {
a=b=0,mv=g=0;
}
} t[maxn<<2];
struct matrix {
giant a[3][3];
matrix (int e=0,int f=0,int g=0,int h=0) {
a[1][1]=e,a[1][2]=f,a[2][1]=g,a[2][2]=h;
}
void operator = (matrix x) {
for (int i=1;i<=2;++i) for (int j=1;j<=2;++j) a[i][j]=x.a[i][j];
}
} mt,rmt,the;
matrix operator * (matrix &x,matrix &y) {
the=matrix();
for (int i=1;i<=2;++i) for (int j=1;j<=2;++j) for (int k=1;k<=2;++k) (the.a[i][j]+=x.a[i][k]*y.a[k][j]+q)%=q;
return the;
}
matrix mi(int y) {
rmt=mt,--y;
while (y) {
if (y&1) rmt=rmt*mt;
y>>=1,mt=mt*mt; // here
}
return rmt; // here
}
void mvit(node &k,int c) {
if (c==0) return;
int a=k.a,b=k.b;
if (c>0) mt=matrix(0,1,1,1); else mt=matrix(-1,1,1,0);
c=abs(c);
mt=mi(c);
k.a=(mt.a[1][1]*a+mt.a[2][1]*b+q)%q,k.b=(mt.a[2][1]*a+mt.a[2][2]*b+q)%q;
}
void pushdown(int x) {
if (!t[x].mv) return;
if (t[x<<1].g) mvit(t[x<<1],t[x].mv),t[x<<1].mv+=t[x].mv;
if (t[x<<1|1].g) mvit(t[x<<1|1],t[x].mv),t[x<<1|1].mv+=t[x].mv;
t[x].mv=0;
}
int qnum(int x,int L,int R,int l,int r) {
if (tic[x]!=tim) t[x].clear(),tic[x]=tim;
if (l>r) return 0;
pushdown(x);
if (L==l && R==r) return t[x].g;
int mid=(L+R)>>1;
if (r<=mid) return qnum(x<<1,L,mid,l,r);
if (l>mid) return qnum(x<<1|1,mid+1,R,l,r);
return qnum(x<<1,L,mid,l,mid)+qnum(x<<1|1,mid+1,R,mid+1,r);
}
void update(int x) {
t[x].g=t[x<<1].g+t[x<<1|1].g;
t[x].a=(t[x<<1].a+t[x<<1|1].a)%q;
t[x].b=(t[x<<1].b+t[x<<1|1].b)%q;
}
void add(int x,int l,int r,int p,int wh,int d) {
if (tic[x]!=tim) t[x].clear(),tic[x]=tim;
pushdown(x);
if (l==r) {
t[x].g+=d;
if (d==1) {
t[x].a=(f[wh]*c[p])%q;
t[x].b=(f[wh+1]*c[p])%q;
} else t[x].a=t[x].b=0;
return;
}
int mid=(l+r)>>1;
if (p<=mid) add(x<<1,l,mid,p,wh,d); else add(x<<1|1,mid+1,r,p,wh,d);
update(x);
}
void moveit(int x,int L,int R,int l,int r,int d) {
if (tic[x]!=tim) t[x].clear(),tic[x]=tim;
if (l>r) return;
pushdown(x);
if (L==l && R==r) {
t[x].mv+=d;
mvit(t[x],d);
return;
}
int mid=(L+R)>>1;
if (r<=mid) moveit(x<<1,L,mid,l,r,d); else
if (l>mid) moveit(x<<1|1,mid+1,R,l,r,d); else {
moveit(x<<1,L,mid,l,mid,d);
moveit(x<<1|1,mid+1,R,mid+1,r,d);
}
update(x);
}
void inc(int x) {
if (tg[x]!=tim) tg[x]=tim,gs[x]=0;
gs[x]++;
if (gs[x]>1) return;
int wh=qnum(1,1,tp,1,x-1)+1;
add(1,1,tp,x,wh,1);
moveit(1,1,tp,x+1,tp,1);
}
void dec(int x) {
if (tg[x]!=tim) tg[x]=tim,gs[x]=0;
gs[x]--;
if (gs[x]) return;
add(1,1,tp,x,0,-1);
moveit(1,1,tp,x+1,tp,-1);
}
giant ans[maxn];
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("my.out","w",stdout);
#endif
n=read(),q=read();
f[1]=f[2]=1;
for (int i=3;i<=n+5;++i) f[i]=(f[i-1]+f[i-2])%q;
qn=sqrt(n);
for (int i=1;i<=n;++i) c[i]=a[i]=read();
sort(c+1,c+n+1);
tp=unique(c+1,c+n+1)-c-1;
for (int i=1;i<=n;++i) a[i]=lower_bound(c+1,c+tp+1,a[i])-c;
int m=read();
for (int i=1;i<=m;++i) b[i].s=read(),b[i].t=read(),b[i].id=i;
sort(b+1,b+m+1);
int nk=-1,l,r;
for (int i=1;i<=m;++i) {
if ((b[i].s-1)/qn>nk) {
nk=(b[i].s-1)/qn;
++tim;
//memset(gs,0,sizeof gs); // here
r=b[i].s-1,l=b[i].s;
}
while (r<b[i].t) inc(a[++r]);
while (l>b[i].s) inc(a[--l]);
while (r>b[i].t) dec(a[r--]);
while (l<b[i].s) dec(a[l++]);
ans[b[i].id]=t[1].a;
}
for (int i=1;i<=m;++i) printf("%lld\n",ans[i]);
}

Codeforces633H-Fibonacci-ish II的更多相关文章

  1. 【TOJ 3600】Fibonacci II (对数+斐波那契通项式)

    描述 2007年到来了.经过2006年一年的修炼,数学神童zouyu终于把0到100000000的Fibonacci数列(f[0]=0,f[1]=1;f[i] = f[i-1]+f[i-2](i> ...

  2. ZOJ3774_Power of Fibonacci

    求fibonacci数列前N个数的K次方和. 通项公式:F[n]=((1+sqrt(5))/sqrt(5)-(1-sqrt(5))/sqrt(5))/sqrt(5). 有点乱,不过由于可以保证最后的结 ...

  3. poj3070 Fibonacci

    Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. F ...

  4. 1143 多少个Fibonacci数

    时间限制:500MS  内存限制:65536K提交次数:270 通过次数:16 题型: 编程题   语言: C++;C Description 给你如下Fibonacci 数的定义: F1 = 1 F ...

  5. Codeforces Gym 100286F Problem F. Fibonacci System 数位DP

    Problem F. Fibonacci SystemTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudg ...

  6. LeetCode: Linked List Cycle II 解题报告

    Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cyc ...

  7. 【CF914G】Sum the Fibonacci 快速??变换模板

    [CF914G]Sum the Fibonacci 题解:给你一个长度为n的数组s.定义五元组(a,b,c,d,e)是合法的当且仅当: 1. $1\le a,b,c,d,e\le n$2. $(s_a ...

  8. Manthan, Codefest 16 H. Fibonacci-ish II 大力出奇迹 莫队 线段树 矩阵

    H. Fibonacci-ish II 题目连接: http://codeforces.com/contest/633/problem/H Description Yash is finally ti ...

  9. codeforces914G Sum the Fibonacci

    题目大意:给定一个长为$n$($n\leq 10^6$)的序列S,定义一个合法的五元组$(a,b,c,d,e)$合法当且仅当 $$ ( S_a \mid S_b ) and S_c and ( S_d ...

  10. CF446C [DZY loves Fibonacci]

    Description Transmission Gate 你需要维护一个长度为\(n \leq 300000\) 的数列,兹词两个操作: 1.给一个区间加上一个fibonacci数列,规定\(f[0 ...

随机推荐

  1. 博科Brocade 300光纤交换机配置zone教程

    光纤交换机作为SAN网络的重要组成部分,在日常应用中非常普遍,本次将以常用的博科交换机介绍基本的配置方法. 博科300实物图: 环境描述: 如上图,四台服务器通过各自的双HBA卡连接至两台博科300光 ...

  2. spark2.2 从入门到精通 视频教程 百度云网盘下载地址

    spark2.2 从入门到精通 视频教程 百度云网盘下载地址 链接:https://pan.baidu.com/s/1sm2Jdmt 密码:rdea

  3. 成都Uber优步司机奖励政策(2月7日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. CC3200使用MQTT的SSL加密证书可用日期修改

    1. 在使用CC3200进行SSL加密的时候,需要证书,但是证书有一个截止日期,如果当前CC3200没有设置这个日期,那么证书通信会失败,需要添加代码 int setDeviceTime() { Sl ...

  5. Ubuntu配置IP

    Ubuntu网络配置的常用系统,于是我学习研究了Ubuntu网络配置,在这里对大家详细介绍下Ubuntu网络配置应用,希望对大家有用Ubuntu网络配置包含了非常好的翻译和容易使用的架构./etc/n ...

  6. MySQL日期、字符串、时间戳互转

    平时比较常用的时间.字符串.时间戳之间的互相转换,虽然常用但是几乎每次使用时候都喜欢去搜索一下用法:本文将作为一个笔记,整理一下三者之间的 转换(即:date转字符串.date转时间戳.字符串转dat ...

  7. Unity编辑器 - 资源批处理工具基类

    Unity编辑器 - 资源批处理工具基类 经常要对资源进行批处理,很多时候都是一次性的需求,于是弄个通用脚本. 工具是个弹出面板,处理过程有进度条,如下: 如图,子类只需要重写几个方法: using ...

  8. Java开发工程师(Web方向) - 01.Java Web开发入门 - 第4章.Maven

    第4章--Maven Maven实战 Java Web应用的部署: 手动式: 编译:javac -cp $CATALINA_HOME/lib/servlet-api.jar web-inf/class ...

  9. 洛谷P1068 分数线划定:sort结构体排序+贪心

    题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行.为了选拔最合适的人才,A市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试. 面试分数线根据计划录取人数的150%划定, ...

  10. Map Reduce Application(Top 10 IDs base on their value)

    Top 10 IDs base on their value First , we need to set the reduce to 1. For each map task, it is not ...