BZOJ4085: [Sdoi2015]音质检测

由于这题太毒了,导致可能会被某些人卡评测,于是成了一道权限题。。。

本蒟蒻表示没钱氪金。。。

但是可以去洛谷/Vijos搞搞事。。。

但是洛谷上只能评测,题面暂时不全。。。

然而Vijos上数据范围不对,应该是洛谷上的数据范围。。。

所以没钱氪金就凑合着看吧。。。

这里附上Vijos的题面。

1958 音质检测

描述

万老板希望在新的智能音乐播放设备IPOOD中,实现对波文件音质性能的评定。

离散的波文件被考虑为长度为N的整数序列:$A_1,A_2,\cdots,A_N$​。所谓的音质性能检测,可以评定任何的一个区间范围$[L,R]$,其音质性能取决于下述评分:

$\Big\{ \sum_{L<i<R} F[A_{i-1}+1]F[A_{i+1}-1] \Big\} \mod (10^9+7)$

其中F是可归纳定义的数列,满足$F[1]=1$,$F[2]=2$且$F[k+2]=F[k+1]+aF[k]+b$对于任何$k\ge 1$成立。其中$a $和$b$为正整系数。

为了可以为用户提供更好的服务体验,并希望对给定的波文件进行修正优化。这一款设备中,还应该支持对波文件的修改。
对于给定的区间范围$[L,R]$,允许用户将$A[L]$至$A[R]$同时增加一,或同时减少一。

格式

输入格式

输入的第一行有两个正整数,波文件的总长度NN,和总的修改与询问次数QQ。

第二行有两个整数,分别表示系数aa和bb。

之后若干行,一共给出NN个正整数A_1A1​到A_NAN​,满足$1 \le A[i] \le 2*10^9$。

之后$Q$行,每行是下述三种形式之一:

$plus~L~R$:将波文件数列中下标在区间$[L,R]$内的元素每一个都加一。

$minus~L~R$:将波文件数列中下标在区间$[L,R]$内的元素每一个都减一。

$query~L~R$:询问区间$[L,R]$的音质性能评分。

修改和询问中,均保证$L\le R$,且保证$A[i]$严格大于总的修改次数加一(修改操作包括plus和minus两种)。

输出格式

输出若干行,每一行对应一次询问,输出一个整数。

样例1

样例输入1

7 7
1 0
3 4 5 6 7 8 9
query 2 4
query 3 7
plus 3 5
query 2 4
plus 4 7
query 3 7
query 1 7

样例输出1

64
1766
104
7479
7687

样例2

样例输入2

7 12
123456789 987654321
1111111111 1222222222 1333333333
1444444444 1555555555 1666666666 1777777777
query 2 4
query 3 7
plus 3 5
minus 4 6
plus 5 7
query 2 4
query 1 6
plus 4 7
minus 1 4
query 3 7
query 2 6
query 1 7

样例输出2

528103209
239947280
528103209
229970829
524160263
336413855
113033289

限制

对于15%的数据,$\(N\le 8000,Q\le 8000\)$。

对于100%的数据,$\(N\le 100000,Q\le 100000,0\le a,b\le 10^9\)$。

此外:

存在15%的数据,每一次修改的区间都是[1,N]。

还存在30%的数据,a=0,b=1。

来源

SDOI 2015 round2 day1


题解Here!

这个题简直就是道神题。。。

首先,线段树+奇奇怪怪的矩阵快速幂应该都能想到。

关键是怎么做对吧。。。

首先考虑一个性质:我们如果有数列的相邻两项$f[i],f[i+1]$。

那么用这两项向后推$k$项其线性表示系数一定。

即表示为$f[i+k]=A\times f[i]+B\times f[i+1]+C$的形式。

那么这样我们预处理这些系数就好了嘛。

注意到维护的是一个乘积的形式,那么我们要维护这个必须得维护$8$个量。

对!你没有看错!$8$个!

将其写成$3\times 3$矩阵的形式转移会比较科学。

注意$a==0$时的特判。

以上是正解。

然后某位巨佬用了$BSGS$预处理$f$函数,简直无敌了:链接

然而我表示并不能码出来,于是自己$YY$了一个方案。

思路大致差不多,但是维护的东西多了点。

我们可以用线段树维护$f[a_{i-1}],f[a_{i-1}+1],f[a_{i-1}-1],f[a_{i+1}],f[a_{i+1}+1],f[a_{i+1}-1]$以及两两乘积和。

加一的时候可以直接用递推式用保存的$f$值求出新的值。

减一的时候也可以解方程求值。

然后开始码码码。。。

好长啊。。。

记得尽量降低时间、空间复杂度,能$return$的地方尽量$return$,以免不必要的搜索导致$TLE/MLE$。

还有一件事,注意开$long\ long$!

还有一件事,做减法的时候如果减了两次,一定要先取模,再$+MOD$,再取模!不然会求出来负数。。。

还有一件事,注意线段树的边界问题,为这个我还浪费了一次提交,药丸。。。

附上炒鸡长的代码(码风较丑不要打我。。。):

#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x,i,j) a[x].data[i-1][j-1]
#define SUM(x,i,j) a[x].sum[i-1][j-1]//为了省空间只能这么干了。。。
#define ADD(x) a[x].c
#define DEL(x) a[x].d
#define LSIDE(x) a[x].l
#define RSIDE(x) a[x].r
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
#define MAXN 300010
#define MOD 1000000007LL
using namespace std;
int n,m;
long long A,B,inv,f[MAXN][4];
struct node{
long long val[4][4];
inline void clean(){
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
val[i][j]=(i==j);
}
friend node operator *(const node x,const node y){
node ret;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++){
ret.val[i][j]=0;
for(int k=1;k<=3;k++)ret.val[i][j]=(ret.val[i][j]+x.val[i][k]*y.val[k][j]%MOD)%MOD;
}
ret.val[3][3]=1;
return ret;
}
}one,two,power[35];
struct Segment_Tree{
long long sum[3][3],data[3][3];
int c,d,l,r;
}a[MAXN<<2];
inline long long read(){
long long date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
long long mexp(long long a,long long b,long long c){
long long s=1;
while(b){
if(b&1)s=s*a%c;
a=a*a%c;
b>>=1;
}
return s;
}
node pow(long long k){
node s;
s.clean();
int i=1;
while(k){
if(k&1)s=s*power[i];
k>>=1;
i++;
}
return s;
}
void function(int i){
node s=one*pow(f[i][0]-2);
f[i][1]=s.val[1][2];f[i][2]=s.val[1][1];
}
void build(){
one.val[1][1]=2;one.val[1][2]=one.val[1][3]=1;
two.val[1][1]=two.val[1][2]=two.val[3][3]=1;
two.val[2][1]=A;two.val[3][1]=B;
for(int i=1;i<=32;i++){
power[i]=two;
two=two*two;
}
}
inline void pushup(int rt){
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++){
DATA(rt,i,j)=(DATA(LSON,i,j)+DATA(RSON,i,j))%MOD;
SUM(rt,i,j)=(SUM(LSON,i,j)+SUM(RSON,i,j))%MOD;
}
}
inline void add(int rt,int l){
for(int i=1;i<=2;i++)SUM(rt,l,i)=SUM(rt,l,i+1);
SUM(rt,l,3)=(SUM(rt,l,2)+A*SUM(rt,l,1)%MOD+B*WIDTH(rt)%MOD)%MOD;
if(l==1){
for(int i=1;i<=2;i++)
for(int j=1;j<=3;j++)
DATA(rt,i,j)=DATA(rt,i+1,j);
for(int i=1;i<=3;i++)DATA(rt,3,i)=(DATA(rt,2,i)+A*DATA(rt,1,i)%MOD+B*SUM(rt,2,i)%MOD)%MOD;
}
else{
for(int i=1;i<=3;i++)
for(int j=1;j<=2;j++)
DATA(rt,i,j)=DATA(rt,i,j+1);
for(int i=1;i<=3;i++)DATA(rt,i,3)=(DATA(rt,i,2)+A*DATA(rt,i,1)%MOD+B*SUM(rt,1,i)%MOD)%MOD;
}
}
inline void del(int rt,int l){
if(A==0){
for(int i=2;i>=1;i--)SUM(rt,l,i+1)=SUM(rt,l,i);
SUM(rt,l,1)=(SUM(rt,l,2)-B*WIDTH(rt)%MOD+MOD)%MOD;
if(l==1){
for(int i=2;i>=1;i--)
for(int j=1;j<=3;j++)
DATA(rt,i+1,j)=DATA(rt,i,j);
for(int i=1;i<=3;i++)DATA(rt,1,i)=(DATA(rt,2,i)-B*SUM(rt,2,i)%MOD+MOD)%MOD;
}
else{
for(int i=1;i<=3;i++)
for(int j=2;j>=1;j--)
DATA(rt,i,j+1)=DATA(rt,i,j);
for(int i=1;i<=3;i++)DATA(rt,i,1)=(DATA(rt,i,2)-B*SUM(rt,1,i)%MOD+MOD)%MOD;
}
return;
}
for(int i=2;i>=1;i--)SUM(rt,l,i+1)=SUM(rt,l,i);
SUM(rt,l,1)=((SUM(rt,l,3)-SUM(rt,l,2)-B*WIDTH(rt)%MOD)*inv%MOD+MOD)%MOD;
if(l==1){
for(int i=2;i>=1;i--)
for(int j=1;j<=3;j++)
DATA(rt,i+1,j)=DATA(rt,i,j);
for(int i=1;i<=3;i++)DATA(rt,1,i)=((DATA(rt,3,i)-DATA(rt,2,i)-B*SUM(rt,2,i)%MOD)*inv%MOD+MOD)%MOD;
}
else{
for(int i=1;i<=3;i++)
for(int j=2;j>=1;j--)
DATA(rt,i,j+1)=DATA(rt,i,j);
for(int i=1;i<=3;i++)DATA(rt,i,1)=((DATA(rt,i,3)-DATA(rt,i,2)-B*SUM(rt,1,i)%MOD)*inv%MOD+MOD)%MOD;
}
}
inline void pushdown_sign(int rt,int l,int c){
if(!c)return;
if(c>0)for(int i=1;i<=c;i++)add(rt,l);
else for(int i=-1;i>=c;i--)del(rt,l);
}
inline void pushdown(int rt){
if(LSIDE(rt)==RSIDE(rt))return;
ADD(LSON)+=ADD(rt);DEL(LSON)+=DEL(rt);
pushdown_sign(LSON,1,ADD(rt));pushdown_sign(LSON,2,DEL(rt));
ADD(RSON)+=ADD(rt);DEL(RSON)+=DEL(rt);
pushdown_sign(RSON,1,ADD(rt));pushdown_sign(RSON,2,DEL(rt));
ADD(rt)=DEL(rt)=0;
}
void buildtree(int l,int r,int rt){
LSIDE(rt)=l;RSIDE(rt)=r;ADD(rt)=DEL(rt)=0;
if(l==r){
for(int i=1;i<=3;i++){
SUM(rt,1,i)=f[l-1][i];
SUM(rt,2,i)=f[l+1][i];
}
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
DATA(rt,i,j)=SUM(rt,1,i)*SUM(rt,2,j)%MOD;
return;
}
int mid=LSIDE(rt)+RSIDE(rt)>>1;
buildtree(l,mid,LSON);
buildtree(mid+1,r,RSON);
pushup(rt);
}
void update_add(int l,int r,int c,int rt){
if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
ADD(rt)+=c;
pushdown_sign(rt,1,c);
return;
}
pushdown(rt);
int mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)update_add(l,r,c,LSON);
if(mid<r)update_add(l,r,c,RSON);
pushup(rt);
}
void update_del(int l,int r,int c,int rt){
if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
DEL(rt)+=c;
pushdown_sign(rt,2,c);
return;
}
pushdown(rt);
int mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)update_del(l,r,c,LSON);
if(mid<r)update_del(l,r,c,RSON);
pushup(rt);
}
long long query(int l,int r,int rt){
if(l>r)return 0;
long long ans=0;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt,3,1);
pushdown(rt);
int mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)ans=(ans+query(l,r,LSON))%MOD;
if(mid<r)ans=(ans+query(l,r,RSON))%MOD;
return ans;
}
void work(){
char ch[7];
int x,y,l,r;
while(m--){
scanf("%s",ch);x=read();y=read();
if(ch[0]=='p'){
l=x+1;r=y+1;
if(r>n)r=n;
if(l<=r)update_add(l,r,1,1);
l=x-1;r=y-1;
if(l<1)l=1;
if(l<=r)update_del(l,r,1,1);
}
else if(ch[0]=='m'){
l=x+1;r=y+1;
if(r>n)r=n;
if(l<=r)update_add(l,r,-1,1);
l=x-1;r=y-1;
if(l<1)l=1;
if(l<=r)update_del(l,r,-1,1);
}
else printf("%lld\n",query(x+1,y-1,1));
}
}
void init(){
n=read();m=read();A=read();B=read();
inv=mexp(A,MOD-2,MOD);
build();
for(int i=1;i<=n;i++){
f[i][0]=read();
function(i);
f[i][3]=(f[i][2]+f[i][1]*A%MOD+B)%MOD;
}
buildtree(1,n,1);
}
int main(){
init();
work();
return 0;
}

BZOJ4085: [Sdoi2015]音质检测的更多相关文章

  1. 洛谷 P3328 【[SDOI2015]音质检测】

    这题我做的好麻烦啊... 一开始想分块来着,后来发现可以直接线段树 首先考虑一个性质,我们如果有数列的相邻两项f[i]和 f[i+1]那么用这两项向后推k项其线性表示系数一定(表示为f[i+k]=a∗ ...

  2. BZOJ 4085:[Sdoi2015]quality(round 2 音质检测)(数据结构)

    居然在考场上把这道题打出来了觉得自己也是有点吊啊(虽然后面就没时间做其他题了囧而且还被卡常数了...) 题解自己写了一份TEX的就直接放上来吧.... 好啦,在谈点什么别的 什么?你在bz上TLE了? ...

  3. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  4. 详解 WebRTC 高音质低延时的背后 — AGC(自动增益控制)

    前面我们介绍了 WebRTC 音频 3A 中的声学回声消除(AEC:Acoustic Echo Cancellation)的基本原理与优化方向,这一章我们接着聊另外一个 "A" - ...

  5. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑

    自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问题.相信有很多人并不是很清楚32位程序与64位程序的区别,以及Program Files (x86),Program Files的区别 ...

  6. Android性能优化之利用LeakCanary检测内存泄漏及解决办法

    前言: 最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到性能优化中如何避免内存泄漏问题时,很少有人全面的回答上来. ...

  7. C++的内存泄漏检测

    C++大量的手动分配.回收内存是存在风险的,也许一个函数中一小块内存泄漏被重复放大之后,最后掏空内存. 这里介绍一种在debug模式下测试内存泄漏的方法. 首先在文件的开头以确定的顺序写下这段代码: ...

  8. 使用 Android Studio 检测内存泄漏与解决内存泄漏问题

    本文在腾讯技术推文上 修改 发布. http://wetest.qq.com/lab/view/63.html?from=ads_test2_qqtips&sessionUserType=BF ...

  9. iOS网络4——Reachability检测网络状态

    一.整体介绍 前面已经介绍了网络访问的NSURLSession.NSURLConnection,还有网页加载有关的webview,基本满足通常的网络相关的开发. 其实在网络开发中还有比较常用的就是网络 ...

随机推荐

  1. rest-client restclient get post写法

    get url = "https://api.weixin.qq.com/sns/jscode2session" data = { appid: "××××", ...

  2. Android TableLayout 表格布局

    TableLayout继承LinearLayout 有多少个TableRow对象就有多少行, 列数等于最多子控件的TableRow的列数 直接在TableLayout加控件,控件会占据一行 Table ...

  3. 【leetcode刷题笔记】Single Number

    题目: Given an array of integers, every element appears twice except for one. Find that single one. No ...

  4. memcached监控脚本

    #!/bin/bash . /etc/init.d/functions |wc -l` -lt ];then action "Memcached Serivce is error." ...

  5. MYSQL函数 Cast和convert的用法详解

    MYSQL Cast函数是非常重要的MYSQL函数,下面就将为您详细介绍MYSQL Cast函数的语法及其使用,希望能让您对MYSQL Cast函数有更多的认识. BINARY     BINARY操 ...

  6. mysql 根据sql查询语句导出数据

    在这里提供2中方式: 建议:可以使用方式二,就不使用方式一. 方式一: 在linux下支持,window下不支持. 进入到mysql的bin目录,或者已经给mysql配置了环境变量就不用进入bin目录 ...

  7. NodeJs实现图片上传

    关于formidable NodeJs实现图片上传,此处主要用了插件:formidable github上关于formidable的资料如下: https://github.com/felixge/n ...

  8. Linux课程---3、Linux远程登录和传输(操作Linux服务器软件)

    Linux课程---3.Linux远程登录和传输(操作Linux服务器软件) 一.总结 一句话总结: xshell:Xshell是一个强大的安全终端模拟软件 Xshell是一个强大的安全终端模拟软件, ...

  9. appium界面元素介绍

    一.主窗口 主页面顶部从左到右依次是: AndroidSettings:android相关的设置 GeneralSettings:全局设置,设置appium相关的内容 DeveloperSetting ...

  10. javascript-JQuery样式篇(一)

    轻量级的JavaScript库,核心依然是JavaScript,不仅兼容了CSS3,还兼容了各种浏览器 强大的选择器,完善的事件机制,出色的Ajax封装,丰富的UI 进入官方网站获取最新的版本 htt ...