CF633H Fibonacci-ish II 莫队、线段树、矩阵乘法
这题除了暴力踩标程和正解卡常数以外是道很好的题目
首先看到我们要求的东西与\(Fibonacci\)有关,考虑矩阵乘法进行维护。又看到\(n \leq 30000\),这告诉我们正解算法其实比较暴力,又因为直接在线解决看起来就比较麻烦,所以考虑离线询问,莫队解决。
我们设斐波那契数列的转移矩阵为\(T = \left( \begin{array}{ccc} 0 & 1 \\ 1 & 1 \end{array} \right)\)
先将\(a\)离散化,用一棵线段树维护矩阵运算。那么我们需要支持的是:插入一个数并使比它大的数对应的\(Fibonacci\)数向后移一个。这个可以在线段树的对应节点打上一个\(T\)的标记,表示向右转移一个,经过这个节点时pushdown下去。删除一个数就打上它的逆矩阵的标记。总复杂度为\(O(n\sqrt{n}logn)\)
Tips:如果你TLE在了第35个点,请尽力卡常,简化取模过程、避免不必要运算(详见代码中pushup过程)
#include<bits/stdc++.h>
//This code is written by Itst
#define lch (x << 1)
#define rch (x << 1 | 1)
#define mid ((l + r) >> 1)
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c)){
if(c == '-')
f = 1;
c = getchar();
}
while(isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 3e4 + 7;
int step = 0 , N , M , Q , T , cnt , num[MAXN] , lsh[MAXN] , times[MAXN] , ans[MAXN];
struct query{
int ind , l , r;
bool operator <(const query a)const{
return l / T == a.l / T ? ((l / T) & 1 ? r > a.r : r < a.r) : l < a.l;
}
}now[MAXN];
struct matrix{
int a[2][2];
int* operator [](int x){return a[x];}
matrix(bool f = 1){if(f) memset(a , 0 , sizeof(a));}
matrix operator *(matrix b){
matrix c;
for(int i = 0 ; i < 2 ; ++i)
for(int j = 0 ; j < 2 ; ++j)
for(int k = 0 ; k < 2 ; ++k)
c[i][j] += a[i][k] * b[k][j];
for(int i = 0 ; i < 2 ; ++i)
for(int j = 0 ; j < 2 ; ++j)
c[i][j] %= M;
return c;
}
matrix operator *(int b){
matrix c(0);
for(int i = 0 ; i < 2 ; ++i)
for(int j = 0 ; j < 2 ; ++j)
c[i][j] = a[i][j] * b;
return c;
}
matrix operator +(matrix b){
matrix c(0);
for(int i = 0 ; i < 2 ; ++i)
for(int j = 0 ; j < 2 ; ++j)
c[i][j] = (a[i][j] + b[i][j]) % M;
return c;
}
bool operator ==(matrix b){
for(int i = 0 ; i < 2 ; ++i)
for(int j = 0 ; j < 2 ; ++j)
if(a[i][j] != b[i][j])
return 0;
return 1;
}
bool operator !=(matrix b){
return !(*this == b);
}
}F , E , G , a , b;
struct node{
matrix ans , mark;
int times;
}Tree[MAXN << 2];
inline void mark(int x , const matrix mark){
Tree[x].mark = Tree[x].mark * mark;
Tree[x].ans = Tree[x].ans * mark;
}
inline void pushdown(int x){
if(Tree[x].mark != E){
mark(lch , Tree[x].mark);
mark(rch , Tree[x].mark);
Tree[x].mark = E;
}
}
inline void pushup(int x){
a = Tree[lch].ans;
b = Tree[rch].ans;
if(Tree[lch].times != 1)
a = a * Tree[lch].times;
if(Tree[rch].times != 1)
b = b * Tree[rch].times;
Tree[x].ans = a + b;
}
void insert(int x , int l , int r , int tar){
if(l == r){
Tree[x].times = lsh[tar];
return;
}
pushdown(x);
if(mid >= tar){
insert(lch , l , mid , tar);
mark(rch , F);
}
else
insert(rch , mid + 1 , r , tar);
pushup(x);
}
void erase(int x , int l , int r , int tar){
if(l == r){
Tree[x].times = 0;
return;
}
pushdown(x);
if(mid >= tar){
erase(lch , l , mid , tar);
mark(rch , G);
}
else
erase(rch , mid + 1 , r , tar);
pushup(x);
}
void init(int x , int l , int r){
Tree[x].times = l != r;
Tree[x].mark = E;
if(l != r){
init(lch , l , mid);
init(rch , mid + 1 , r);
}
else
Tree[x].ans = F;
}
inline void add(int a){
if(!times[a]++)
insert(1 , 1 , cnt , a);
++step;
}
inline void del(int a){
if(!--times[a])
erase(1 , 1 , cnt , a);
++step;
}
int main(){
N = read();
M = read();
T = sqrt(N);
E[0][0] = E[1][1] = F[0][1] = F[1][0] = F[1][1] = G[1][0] = G[0][1] = 1;
G[0][0] = M - 1;
for(int i = 1 ; i <= N ; ++i)
num[i] = lsh[i] = read();
sort(lsh + 1 , lsh + N + 1);
cnt = unique(lsh + 1 , lsh + N + 1) - lsh - 1;
for(int i = 1 ; i <= N ; ++i)
num[i] = lower_bound(lsh + 1 , lsh + cnt + 1 , num[i]) - lsh;
for(int i = 1 ; i <= cnt ; ++i)
lsh[i] %= M;
Q = read();
for(int i = 1 ; i <= Q ; ++i){
now[i].ind = i;
now[i].l = read();
now[i].r = read();
}
sort(now + 1 , now + Q + 1);
int L = 1 , R = 0;
init(1 , 1 , cnt);
for(int i = 1 ; i <= Q ; ++i){
while(R < now[i].r)
add(num[++R]);
while(L > now[i].l)
add(num[--L]);
while(R > now[i].r)
del(num[R--]);
while(L < now[i].l)
del(num[L++]);
ans[now[i].ind] = Tree[1].ans[0][1] * Tree[1].times % M;
}
cerr << step << endl;
for(int i = 1 ; i <= Q ; ++i)
printf("%d\n" , ans[i]);
return 0;
}
CF633H Fibonacci-ish II 莫队、线段树、矩阵乘法的更多相关文章
- 【CF633H】Fibonacci-ish II 莫队+线段树
[CF633H]Fibonacci-ish II 题意:给你一个长度为n的序列$a_i$.m个询问,每个询问形如l,r:将[l,r]中的所有$a_i$排序并去重,设得到的新数列为$b_i$,求$b_1 ...
- Manthan, Codefest 16 H. Fibonacci-ish II 大力出奇迹 莫队 线段树 矩阵
H. Fibonacci-ish II 题目连接: http://codeforces.com/contest/633/problem/H Description Yash is finally ti ...
- Codeforces 666E E - Forensic Examination SA + 莫队 + 线段树
E - Forensic Examination 我也不知道为什么这个复杂度能过, 而且跑得还挺快, 数据比较水? 在sa上二分出上下界, 然后莫队 + 线段树维护区间众数. #include< ...
- 洛谷P3246 序列 [HNOI2016] 莫队/线段树+扫描线
正解:莫队/线段树+扫描线 解题报告: 传送门! 似乎是有两种方法的,,,所以分别港下好了QAQ 第一种,莫队 看到这种询问很多区间之类的就会自然而然地想到莫队趴?然后仔细思考一下,发现复杂度似乎是欧 ...
- [hdoj6483][莫队+线段树/ST]
A Sequence Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- [bzoj4358]permu:莫队+线段树/回滚莫队
这道题是几天前水过去的,现在快没印象了,水一发. 首先我们看到它让求解的是最长的值域 连续段长度,很好. 然后就想到了山海经,但但是我还没有做. 然后又想到了很久以前的一次考试的T3旅馆hotel(我 ...
- BZOJ 4129 树上带修莫队+线段树
思路: 可以先做做BZOJ3585 是序列上的mex 考虑莫队的转移 如果当前数字出现过 线段树上把它置成1 对于询问 二分ans 线段树上查 0到ans的和 是不是ans+1 本题就是把它搞到了序列 ...
- 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法
C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...
- LOJ2980 THUSC2017大魔法师(线段树+矩阵乘法)
线段树每个节点维护(A,B,C,len)向量,操作即是将其乘上一个矩阵. #include<iostream> #include<cstdio> #include<cma ...
- hdu 5068(线段树+矩阵乘法)
矩阵乘法来进行所有路径的运算, 线段树来查询修改. 关键还是矩阵乘法的结合律. Harry And Math Teacher Time Limit: 5000/3000 MS (Java/Others ...
随机推荐
- 常见编码GBK、GB2312、UTF-8、ISO-8859-1的区别
https://blog.csdn.net/shijing_0214/article/details/50908144 在项目开发中,会经常遇到不同的编码方式.不管什么编码,都是信息在计算机中的一种表 ...
- 在td中的输入英文为什么不自动换行???
在表格中如果输入纯汉字,表格中的内容会根据表格大小进行换行,若果一个老外不会写汉字,写了一堆英文,表格的宽度会拉的很长,超过规定宽度 解决方法是在table中加上style="table-l ...
- [Linux.NET]在CentOS 7.x中编译方式安装Nginx
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.由俄罗斯的程序设计师Igor Sysoev所开发,供俄罗斯大型的 ...
- 山西WebGIS项目总结
有一段时间没写blog了,说实话,最近的心态一直在变化,看了一部日剧,回想了这一年所学所见,感觉生活目标变了. 做国土项目这段时间不是很忙,由于数据一直给不到位,时间拖得很久,所以在这期间也在继续学习 ...
- [20171120]关于find 软连接问题.txt
[20171120]关于find 软连接问题.txt --//上个星期为了测试oracle参数filesystemio_options,将数据库做了一次移动.但是我使用find对软链接目录查询时--/ ...
- tkinter中button按钮控件(三)
button控件 简单的实现: import tkinter wuya = tkinter.Tk() wuya.title("wuya") wuya.geometry(" ...
- python第六十八天--第十二周作业
主题: 需求: 用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下讲师视图 管理班级,可创建班级,根据学员qq号把学员加入班级 可创建指定班级的上课纪录,注意一节上课纪录对应多条 ...
- C# RSA 加密
class Sign_verifySign { #region prepare string to sign. //example format: a=123&b=xxx&c (wit ...
- Hbase-2.0.0_03_Hbase数据模型
1. hbase数据模型 1.1. HBase数据模型术语 Table HBase表由多行组成. Row HBase中的一行由一个行键和一个或多个列组成,列的值与这些列相关联.存储行时,按行键按字母顺 ...
- IE浏览器打不开网页的解决方法
前阵子一下子安装了很多软件,后来使用IE游览器的时候,莫名其妙的打不开网页,虽然用其他浏览器(比如谷歌.火狐)可以正常浏览网页,但是由于很多软件内嵌页面都会调用Windows的IE浏览器来加载,所以I ...