LINK


题目大意

给你一个序列a,Q次询问,每次询问\([l,r]\)

把\([l,r]\)的数排序去重,得到序列b,f是斐波那契数列

求\(\sum_{b=1}^{len} b_if_i\)

思路

发现单次如果加入和减去一个数

只需要把这个数的贡献加上/减去,然后把大于他的数斐波那契数的下标++/--

这个东西如果可以维护就可以完成单次加入个删除了

那么就可以用莫队来把询问离线处理

然后考虑加入一个数或者删除一个数

先离散化,用线段树维护起来

每个区间直接维护这个区间的答案

因为线段树需要累加标记,所以直接考虑把下表标加上k的贡献??

这东西需要一个结论\(f_{n+k}=f_{n}f_{k+1}+f_{n-1}{k}\)

发现\(\sum_{b=1}^{len} b_if_{i+k}=\sum_{b=1}^{len}b_i*f_if_{k+1}+\sum_{b=1}^{len}b_i*f_{i-1}f_{k}\)

发现只需要区间只需要维护两个值\(\sum_{b=1}^{len}b_if_i\)和\(\sum_{b=1}^{len}b_if_{i-1}\)就可以了

那么\(\sum_{b=1}^{len}b_if_{i-1}\),咋维护?

\(\sum_{b=1}^{len}b_if_{i-1}=\sum_{b=1}^{len}b_if_if_k+\sum_{b=1}^{len}f_{i-1}f_{k-1}\)

因为有减法操作,所以还需要处理斐波那契数列下标是负数的情况,加上偏移量逆推就行了

然后还需要一些卡常技巧

比如在单点加上贡献的时候,每次向左走就可以把右边区间的下标加上

然后可以线段树非递归卡卡常。。。。

能不取模就别取模


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 3e4 + 10;
int n, q, Mod;
int cnt[N] = {0}, pre[N], tot = 0, a[N];
int ans[N], f[N << 1];
struct Query {
int l, r, id;
} Q[N];
int block[N], siz_of_block;
bool cmp(Query a, Query b) {
if (block[a.l] == block[b.l]) return a.r < b.r;
return a.l < b.l;
}
int add(int a, int b) {
return (a += b) >= Mod ? a - Mod : a;
}
int sub(int a, int b) {
return (a -= b) < 0 ? a + Mod : a;
}
int mul(int a, int b) {
return 1ll * a * b % Mod;
}
void init() {
f[N] = 0, f[N + 1] = 1;
fu(i, N + 2, (N << 1) - 1) f[i] = add(f[i - 2], f[i - 1]);
fd(i, N - 1, 1) f[i] = sub(f[i + 2], f[i + 1]);
}
#define LD (t << 1)
#define RD (t << 1 | 1)
int val1[N << 2], val2[N << 2], tag[N << 2];
void pushup(int t) {
val1[t] = add(val1[LD], val1[RD]);
val2[t] = add(val2[LD], val2[RD]);
}
void pushnow(int t, int vl) {
int lastval1 = val1[t];
int lastval2 = val2[t];
tag[t] += vl;
val1[t] = (lastval1 * f[N + vl + 1] + lastval2 * f[N + vl]) % Mod;
val2[t] = (lastval1 * f[N + vl] + lastval2 * f[N + vl - 1]) % Mod;
}
void pushdown(int t) {
if (tag[t]) {
pushnow(LD, tag[t]);
pushnow(RD, tag[t]);
tag[t] = 0;
}
}
void insert(int t, int l, int r, int pos) {
while (l < r) {
pushdown(t);
int mid = (l + r) >> 1;
if (pos <= mid) {
pushnow(RD, 1);
t = LD, r = mid;
} else {
t = RD;
l = mid + 1;
}
}
val1[t] = mul(pre[l], f[N + tag[t] + 1]);
val2[t] = mul(pre[l], f[N + tag[t]]);
while (t >>= 1) pushup(t);
}
void remove(int t, int l, int r, int pos) {
while (l < r) {
pushdown(t);
int mid = (l + r) >> 1;
if (pos <= mid) {
pushnow(RD, -1);
t = LD, r = mid;
} else {
t = RD;
l = mid + 1;
}
}
val1[t] = val2[t] = 0;
while (t >>= 1) pushup(t);
}
void insert(int pos) {
if (++cnt[pos] == 1) insert(1, 1, tot, pos);
}
void remove(int pos) {
if (--cnt[pos] == 0) remove(1, 1, tot, pos);
}
int main() {
//freopen("input.txt", "r", stdin);
Read(n), Read(Mod);
init();
fu(i, 1, n) {
Read(a[i]);
pre[i] = a[i];
}
sort(pre + 1, pre + n + 1);
tot = unique(pre + 1, pre + n + 1) - pre - 1;
fu(i, 1, n) a[i] = lower_bound(pre + 1, pre + tot + 1, a[i]) - pre;
siz_of_block = sqrt(n);
fu(i, 1, n) block[i] = (i - 1) / siz_of_block + 1;
Read(q);
fu(i, 1, q) Read(Q[i].l), Read(Q[i].r), Q[i].id = i;
sort(Q + 1, Q + q + 1, cmp);
int l = 1, r = 0;
fu(i, 1, q) {
while (r < Q[i].r) insert(a[++r]);
while (r > Q[i].r) remove(a[r--]);
while (l > Q[i].l) insert(a[--l]);
while (l < Q[i].l) remove(a[l++]);
ans[Q[i].id] = val1[1];
}
fu(i, 1, q) {
Write(ans[i]);
putchar('\n');
}
return 0;
}

Codeforces 633H Fibonacci-ish II【线段树】的更多相关文章

  1. UVA10869 - Brownie Points II(线段树)

    UVA10869 - Brownie Points II(线段树) 题目链接 题目大意:平面上有n个点,Stan和Ollie在玩游戏,游戏规则是:Stan先画一条竖直的线作为y轴,条件是必需要经过这个 ...

  2. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  3. Codeforces 446C —— DZY Loves Fibonacci Numbers(线段树)

    题目:DZY Loves Fibonacci Numbers 题意比較简单,不解释了. 尽管官方的题解也是用线段树,但还利用了二次剩余. 可是我没有想到二次剩余,然后写了个感觉非常复杂度的线段树,还是 ...

  4. codeforces 22E XOR on Segment 线段树

    题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...

  5. CDOJ 1259 昊昊爱运动 II 线段树+bitset

    昊昊爱运动 II 昊昊喜欢运动 他N天内会参加M种运动(每种运动用一个[1,m]的整数表示) 现在有Q个操作,操作描述如下 昊昊把第l天到第r天的运动全部换成了x(x∈[1,m]) 问昊昊第l天到第r ...

  6. Codeforces 588E. A Simple Task (线段树+计数排序思想)

    题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...

  7. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

  8. SPOJ 1557. Can you answer these queries II 线段树

    Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/pr ...

  9. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  10. Codeforces 444C DZY Loves Colors(线段树)

    题目大意:Codeforces 444C DZY Loves Colors 题目大意:两种操作,1是改动区间上l到r上面德值为x,2是询问l到r区间总的改动值. 解题思路:线段树模板题. #inclu ...

随机推荐

  1. Rancher在Catalog中 使用Helm Chart安装应用

    1. 首先在github上创建一个项目: 这里以我的项目为例:https://github.com/hankuikuide/cis-rancher-cattle 可以看出里出其实除了chart文件什么 ...

  2. python正则表达式 Python Re模块

    最近在学python 练习的时候随手写的,方便以后自己参考~如果能对其他同学有所帮助就再好不过了 希望大家指正哦~  我会随时整理的,先这样~ 正则表达式 1.元字符([ ]),它用来指定一个char ...

  3. Nginx的坑

    Nginx的重启命令:./nginx -s reload  有时候没有效果,原因不知, 要重启可以使用:killall nginx,然后./nginx  (就是先kill掉Nginx,然后再重启Ngi ...

  4. SSH两种验证方式原理

    本帖转自 http://www.cnblogs.com/hukey/p/6248468.html SSH验证方式有两种,分别为用户密码认证以及密钥认证. 1.用户密码认证方式 说明: (1) 当客户端 ...

  5. 基于cornerstone.js的cornerstoneWADOImageLoader

    上一篇简单介绍了cornerstone.js的相关使用介绍和基于cornerstone的web库cornerstoneWADOImageLoader,在实际开发中遇到了相关的一些问题,在这里说明一下, ...

  6. HTML5 history API,创造更好的浏览体验

    HTML5 history API有什么用呢? 从Ajax翻页的问题说起 请想象你正在看一个视频下面的评论,在翻到十几页的时候,你发现一个写得稍长,但非常有趣的评论.正当你想要停下滚轮细看的时候,手残 ...

  7. 算法总结1:K-邻近算法

    1. 算法原理: K-邻近算法的原理很简单,就是用你的“邻居”来推断出你的类别.用于离散型数据分析处理. 例子1:如下图有ABCD四个用于参考的样本点,都已知晓自己的坐标位置,这时E来了,不清楚自己的 ...

  8. torch7 调用caffe model 作为pretrain

    torch7 调用caffe model 作为pretrain torch7 caffe preTrain model zoo torch7 通过 loadcaffe 包,可以调用caffe训练得到的 ...

  9. torch 深度学习 (2)

    torch 深度学习 (2) torch ConvNet 前面我们完成了数据的下载和预处理,接下来就该搭建网络模型了,CNN网络的东西可以参考博主 zouxy09的系列文章Deep Learning ...

  10. 十六、dbms_space_admin(提供了局部管理表空间的功能)

    1.概述 作用:提供了局部管理表空间的功能 2.包的组成 1).segment_verify作用:用于检查段的区映像是否与位图一致语法:dbms_space_admin.segment_verify( ...