CodeForces - 633 H Fibonacci-ish II(莫队+线段树)
题意:给你一个长为n的序列,给你一个mod,再给你q次询问,每次区间查询P(a) = a1·F1 + a2·F2 + ... + an·Fn F为对应的斐波那契数列,a1为以排好序且不重复的区间内的数
参考博客:https://blog.csdn.net/zearot/article/details/50850792
题解:首先对这道题目我们能够想到用莫队处理区间的查询,那么我们只要想办法把莫队的左右区间扩展和收缩解决就可以,那么怎么解决下一个出现的ai是第几大,以及比ai要大的数后移(或前移)的操作就需要用到线段树的维护,区间维护要移动的距离,正数表示向右,负数表示向左。
斐波那契的一个公式F[i-1]*F[k]+F[i]*F[k+1]=F[i+k],所以只要每次维护两个值,一个是第一行的值,一个是第二行的值,线段树维护要移动的距离,
(图是我盗的,盗自上面的博客)
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #include<ctime> #include<unordered_map> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=3e4+10; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; int a[N]; struct node {int l,r,id; }Q[N]; int pos[N]; int L=1,R=0; int ans=0; int res[N]; int n,q,m; int mm=1;//离散化后的个数 int fib[N<<1]; int rnk[N];//记录去重后并且排序的a[i] int rnkA[N];//记录每个a[i]的第几大 int mp[N];//记录区间内有多少个a[i] int V[N<<2],VL[N<<2],S[N<<2];//S是记录了区间要移动的长度 正数为向右,负数为向左 bool cmp(node x,node y){if(pos[x.l]==pos[y.l])return x.r<y.r;return pos[x.l]<pos[y.l]; } void init(){//离散化sort(rnk+1,rnk+1+n);for(int i=2;i<=n;i++){//去重if(rnk[i-1]!=rnk[i]){rnk[++mm]=rnk[i];}}for(int i=1;i<=n;i++){//离散后为得到每个a[i]是第几大而进行二分int l=1,r=mm,ans = 0;while(l<=r){int mid=(l+r)>>1;if(rnk[mid]<=a[i]){l=mid+1;ans=mid;}else r=mid-1;}rnkA[i]=ans;} } //接下来所有的操作都是在1--mm这个区间内进行线段树操作 void shift(int rt,int s){int l=(VL[rt]*fib[mm+s]+V[rt]*fib[mm+s+1])%m;int r=(VL[rt]*fib[mm+s-1]+V[rt]*fib[mm+s])%m;V[rt]=l;VL[rt]=r; } void pushup(int rt){V[rt]=(V[rt<<1]+V[rt<<1|1])%m;VL[rt]=(VL[rt<<1]+VL[rt<<1|1])%m; }void pushdown(int rt){if(S[rt]){S[rt<<1]+=S[rt];S[rt<<1|1]+=S[rt];shift(rt<<1,S[rt]);shift(rt<<1|1,S[rt]);S[rt]=0;} }void move(int x,int l,int r,int rt){if(l==r){V[rt]=VL[rt]=0; return ;}pushdown(rt);int m=(l+r)>>1;if(x<=m){move(x,lson);S[rt<<1|1]--;shift(rt<<1|1,-1);}else move(x,rson);pushup(rt); }void Insert(int x,int l,int r,int rt){if(l==r){VL[rt]=rnk[l]%m*fib[mm+S[rt]]%m;V[rt]=rnk[l]%m*fib[mm+S[rt]+1]%m;return ;}int m=(l+r)>>1;pushdown(rt);if(x<=m){Insert(x,lson);S[rt<<1|1]++;shift(rt<<1|1,1);}else Insert(x,rson);pushup(rt); }void del(int x){mp[rnkA[x]]--;if(mp[rnkA[x]]==0)move(rnkA[x],1,mm,1); }void add(int x){mp[rnkA[x]]++;if(mp[rnkA[x]]==1)Insert(rnkA[x],1,mm,1); }void getfib(){fib[mm]=0;fib[mm+1]=1;for(int i=2;i<=mm;i++)fib[mm+i]=(fib[mm+i-1]+fib[mm+i-2])%m;for(int i=1;i<=mm;i++)fib[mm-i]=(fib[mm-i+2]-fib[mm-i+1]+m)%m; }int main(){scanf("%d%d",&n,&m);int sz=sqrt(n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);pos[i]=i/sz;rnk[i]=a[i];}init();getfib();scanf("%d",&q);for(int i=1;i<=q;i++){scanf("%d%d",&Q[i].l,&Q[i].r);Q[i].id=i;}sort(Q+1,Q+1+q,cmp);for(int i=1;i<=q;i++){while(L>Q[i].l){L--;add(L);}while(L<Q[i].l){del(L);L++;}while(R<Q[i].r){R++;add(R);}while(R>Q[i].r){del(R);R--;}res[Q[i].id]=V[1];}for(int i=1;i<=q;i++){printf("%d\n",res[i]);}return 0; }
转载于:https://www.cnblogs.com/Mrleon/p/8946625.html
CodeForces - 633 H Fibonacci-ish II(莫队+线段树)相关推荐
- 牛客练习赛85 数学家的迷题 (带修莫队/线段树)
题意: 1:将a[id]a[id]a[id]的值改为xxx. 2:令t=a[l]×a[l+1]×...×a[r−1]×a[r]t=a[l]×a[l+1]×...×a[r−1]×a[r]t=a[l]×a ...
- HDU - 5381 The sum of gcd(莫队/线段树区间合并)
题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,再给出 mmm 次询问,每次询问需要回答区间 [L,R][L,R][L,R] 内所有子区间的 gcdgcdgcd 之和.更具体的,对于询问 ...
- SPOJ - DQUERY D-query(莫队/线段树+离线/主席树)
题目链接:点击查看 题目大意:给出一个由n个数组成的序列,再给出m次查询,每次查询区间[l,r]中有多少个不同的数 题目分析:莫队模板题,直接套板子就好了 有点意思的是函数返回值为布尔类型,然后没有r ...
- 51nod-猴猴的比赛【莫队,线段树】
正题 题目链接:https://www.51nod.com/Contest/Problem.html#contestProblemId=1150 题目大意 给出两颗nnn个点的树,求有多少个点(i,j ...
- codeforces 617E XOR and Favorite Number 莫队
https://vjudge.net/problem/CodeForces-617E 题目大意:给nnn个数,mmm个询问,以及一个数kkk,每次询问要输出[l,r][l,r][l,r]内满足a[i] ...
- CodeForces - 617E XOR and Favorite Number(莫队)
题目链接:点击查看 题目大意:给出一个由n个数组成的数列,现在给出m组询问,每次询问包含一个l和一个r,要求回答在闭区间[l,r]中有多少组(i,j)满足[i,j]闭区间内的所有数的异或和等于k 题目 ...
- Hdu 6534 Chika and Friendly Pairs 莫队算法+树状数组
题目链接 题意求给区间[L,R]中有少对(i,j)满足i<j且abs(a[i]-a[j])<=k. 首先来说暴力的方法就是离散化,然后用树状数组来维护,但是m次询问,m很大,所以说一定会t ...
- P4113 [HEOI2012]采花 【树状数组 AC】【莫队/主席树 TLE】
传送门 题意简述:给定一个长度为 n 的序列,有 m 次询问,每次询问一段区间,求区间中有多少个数出现次数超过 1 次 这道题真的有点恶心...在洛谷上属于莫队,但是莫队会T,数据居然有2e6.莫队的 ...
- Bzoj3236:[Ahoi2013]作业:莫队算法+树状数组
题目链接:3236:[Ahoi2013]作业 这题-- 很水的一道莫队,只要用一个树状数组维护数值出现的前缀和就行就行 然而-- 可怜的我真是T得蛋疼了QAQ 先是写了一发裸莫队,T 卧槽T了? 快速 ...
- Codeforces 914D - Bash and a Tough Math Puzzle 线段树,区间GCD
题意: 两个操作, 单点修改 询问一段区间是否能在至多一次修改后,使得区间$GCD$等于$X$ 题解: 正确思路; 线段树维护区间$GCD$,查询$GCD$的时候记录一共访问了多少个$GCD$不被X整 ...
最新文章
- 胡玮炜卸任摩拜CEO,或将成为美团大裁员的开端
- Oracle用户密码过期和用户被锁解决方法【转】
- python输出文本-Python基础练习,查询文本内容并输出;
- 模糊数学笔记:七、模糊综合评判决策
- 二进制包方式安装部署三节点k8s
- 直播预告 | 亚马逊高级应用科学家熊元骏:人类行为理解研究进展
- php去字符串空格,php怎么去掉字符串中空格
- linux 内核4.12,Linux Kernel 4.12 发布,最新的稳定版内核
- 微博:冬奥期间累计共清理相关违规内容近31万条
- 提高Axure设计效率的10条建议 (转)
- linux g++ 链接,Linux G++将64位共享库代码链接到静态库
- JavaSE基础_java简介和环境搭建_2
- golang中值类型/指针类型的变量区别总结
- 五子棋算杀c语言,什么是五子棋的做杀
- python中哪些词是敏感字词_敏感词库(收集2017年最新最全敏感词) 2017 最新版
- win10开启ftp连接不上的正确解决方案
- (二十四)美萍酒店管理系统:散客开单
- jane street market prediction 冠军方案 经验分享 (1/3)
- Photoshop 2023(版本24.0)新增功能和软件下载
- 升腾c10,华为ct3100安装nextcloud,KodExplorer网盘
热门文章
- Java11完全兼容Java8吗_Java11正式发布,要不要升级请看这里!
- Xiao Shenyang's classic lines
- 手机内存如何快速自清理
- python3 flask 使用Mysql数据库
- 使用 sed 替换字符串中最后一次出现的字符
- ubuntu CA安装 证书申请
- 创建一个Employee类
- linux 编辑 iso文件格式,这两款实用的光盘映像文件制作编辑软件让你处理ISO文件易如反掌...
- MBR、主分区、扩展分区、逻辑分区、活动分区、系统分区、启动分区讲解
- P问题、NP问题、NPC问题(算法复杂性,计算复杂性)