【tsinsen A1490】osu!(乔明达) 矩阵+线段树
试题来源
2013中国国家集训队第二次作业
问题描述
osu!是一个基于《押忍!战斗!应援团》《精英节拍特工》《太鼓达人》等各种音乐游戏做成的一款独特的PC版音乐游戏。游戏中,玩家需要根据音乐的节奏,通过鼠标点击或敲击按键合成一首歌曲。
一张osu!的地图是由若干个“音”排列而成的。在本题中,对于每个音我们只需要考虑成功点击和错过(miss)这两种情况。对于一张osu!地图,玩家的完成情况可以用一个01串表示(0代表miss,1代表成功)。在本题中,使用如下计分规则:将玩家完成一张地图的01串中所有的0删去,则这个串可能会断裂成若干段连续的1。对于一段长度为L的1(L≥1),你的总分会增加L^2+L+1。例如:一张地图有10个音,某玩家完成情况为1011101110,则删除所有0后得到的是“1”“111”和“111”。因此这个玩家的得分为(1+1+1)+(9+3+1)+(9+3+1)=29。
ACMonster要给Sandytea出一张osu!的地图。在一张图中,不同音对于Sandytea而言难度可能是不同的。我们定义一个音的难度系数为Sandytea成功完成这个音的概率,因此这个难度系数是介于0和1之间的。
现在ACMonster写下了一个包含N个音的序列,但是他不想直接把这个序列做成地图,而是选择其中的某个片段。设S(X,Y)代表序列上第X个音到第Y个音构成的序列,ACMonster想知道如果把S(X,Y)对应的序列做成地图,Sandytea的期望得分是多少。有时ACMonster会觉得某个音的难度系数不太合理,因此要进行修改。请你想办法处理ACMonster的修改,并回答他提出的问题。
输入格式
第一行包含两个数N和M,N代表序列中音的个数,M代表询问及修改的总次数。
第二行至第(N+1)行每行包含一个实数,第i行的实数表示第(i-1)个音的难度系数。
第(N+2)行至第(N+M+1)行每行包含三个数Type,X和Y。
如果Type=0,代表ACMonster询问S(X,Y)的期望得分,保证X和Y为整数,1≤X≤Y≤N。
如果Type=1,代表ACMonster要把第X个音的难度系数修改为Y,保证X为整数,1≤X≤N,0≤Y≤1。
输出格式
对于输入中所有询问,按照出现的顺序输出相应的答案,四舍五入保留两位小数。
样例输入
2 3
0.5
0.5
0 1 2
1 1 0
0 1 2
样例输出
3.25
1.50
样例说明
对于第一次询问,00,01,10,11这四种情况出现的概率均为1/4,得分分别为0,3,3,7。因此期望得分为(0+3+3+7)/4=3.25。
对于第二次询问,00,01这两种情况出现的概率均为1/2,得分分别为0,3。因此期望得分为(0+3)/2=1.50。
数据规模和约定
20%的数据满足N,M≤5000;
60%的数据满足N,M≤50000;
100%的数据满足N,M≤500000。
小规模数据可以套bzoj4318
满分算法用线段树,分别维护平方、一次方、1,然后1和一次方可以直接合并,平方那个推一下发现是一个线性递推式,可以构造3*3的矩阵。
因为这个题及其卡常,我们发现矩乘的时候真正有用的变量只有四个,所以可以分别维护,减少常数
然而并没有什么卵用,我的代码是75分,被卡常了,求老司机带我卡常
我发现我风格分好高
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int SZ = 500010;
const int INF = 1000000010;
struct segment{int l,r;double s0,s1,a11,a12,a31,a32,lx,rx;
}tree[SZ << 2];
double a[SZ];
void update(segment &p,const segment &a,const segment &b)
{p.s0 = a.s0 + b.s0 - a.rx * b.lx;p.s1 = a.s1 + b.s1;p.a11 = a.a11 * b.a11;p.a12 = a.a11 * b.a12 + a.a12;p.a31 = a.a31 * b.a11 + b.a31;p.a32 = a.a31 * b.a12 + a.a32 + b.a32;p.lx = a.lx; p.rx = b.rx;
}
void build(int p,int l,int r)
{tree[p].l = l,tree[p].r = r;if(l == r){tree[p].lx = tree[p].rx = tree[p].s1 = tree[p].s0 = a[l];tree[p].a11 = tree[p].a31 = tree[p].a32 = a[l];tree[p].a12 = a[l] * 2;return ; }int mid = (l + r) >> 1;build(p << 1,l,mid); build(p << 1 | 1,mid + 1,r);update(tree[p],tree[p << 1],tree[p << 1 | 1]);
}
segment ask(int p,int l,int r)
{if(l == tree[p].l && tree[p].r == r)return tree[p]; int mid = (tree[p].l + tree[p].r) >> 1;if(l > mid) return ask(p << 1 | 1,l,r);else if(r <= mid) return ask(p << 1,l,r);else{segment a = ask(p << 1,l,mid),b = ask(p << 1 | 1,mid + 1,r);segment ans;update(ans,a,b);return ans;}
}
void change(int p,int pos,double d)
{if(tree[p].l == tree[p].r){tree[p].lx = tree[p].rx = tree[p].s1 = tree[p].s0 = d;tree[p].a11 = tree[p].a31 = tree[p].a32 = d;tree[p].a12 = d * 2;return ;}int mid = (tree[p].l + tree[p].r) >> 1;if(pos <= mid) change(p << 1,pos,d);else change(p << 1 | 1,pos,d);update(tree[p],tree[p << 1],tree[p << 1 | 1]);
}
void scan(int &n)
{n = 0;char a = getchar();while(a < '0' || a > '9') a = getchar();while(a >= '0' && a <= '9') n = n * 10 + a - '0',a = getchar();
}
int main()
{int n,m;scan(n); scan(m);for(int i = 1;i <= n;i ++)scanf("%lf",&a[i]);build(1,1,n);while(m --){int opt;scan(opt);if(opt == 0){int x,y;scan(x); scan(y);segment ans = ask(1,x,y);printf("%.2lf\n",ans.s0 + ans.s1 + ans.a32);}else{int x; double y;scan(x);scanf("%lf",&y);change(1,x,y);}}return 0;
}
【tsinsen A1490】osu!(乔明达) 矩阵+线段树相关推荐
- 【周末狂欢赛6】[AT1219]历史研究(回滚莫队),大魔法师(矩阵+线段树),单峰排列
文章目录 T1:单峰排列 题目 题解 code T2:历史研究 题目 题解 code T3:大魔法师 题目 题解 code 我可能这辈子都更不出来狂欢赛5了,先咕咕 T1:单峰排列 题目 一个n的全排 ...
- ZJOI2019 线段树
ZJOI2019 线段树 题意: 题目传送门 题解: 来讲一个非常卡常的矩阵+线段树做法.首先转化一下题意,直接将\(2^m\)棵线段树建出来一定是不现实的,我们对于每一个节点,记录这个节点在所有线段 ...
- A1490. osu!(乔明达)|概率与期望|卡常|矩阵
60TLE 把要求信息拆分 用 线段树和矩阵维护 upd:fqk太劲了 加个读入优化就A过去了 #include <cstdio> #include <iostream> #i ...
- [TsinsenA1490] osu!(乔明达)
作为一名osu!玩家,这道题成功吸引到了我... 题意 长度为n的序列,给出每一个数字可能为1的概率aia_i,每个数字为0的概率为1−ai1-a_i.两个操作:修改某个数字的概率,询问一段区间得分期 ...
- CodeForces - 1252K Addition Robot(线段树维护矩阵)
题目链接:点击查看 题目大意:给出一个只由 A 和 B 组成的字符串 s ,需要完成 m 次操作,每次操作分为两种类型: 1 l r :将 [ l , r ] 内的字符串 A 变成 B,B 变成 A ...
- 牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)
题目链接:点击查看 题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作: 1 pos k b:将 ...
- 2019ICPC(南昌) - Hello 2019(动态规划+线段树维护矩阵)
题目链接:点击查看 题目大意:给出一个长度为n的只由数字组成的字符串,再给出m个询问,每次询问给出闭区间[l,r],求区间内想要包含"9102",但不包含"8102&qu ...
- 线段树 + 矩阵 --- ZOJ 3772 Calculate the Function
Calculate the Function Problem's Link: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCod ...
- New Year and Old Subsequence CodeForces - 750E(线段树+矩阵dp)2019南昌icpc网络赛Hello 2019
A string t is called nice if a string "2017" occurs in t as a subsequence but a string &qu ...
最新文章
- git 强制推送_Git 常用命令清单,掌握这些,轻松驾驭版本管理
- 扇贝编程python是干嘛的-产品观察 | 以对话式互动学习撬动转化,扇贝编程瞄准职教市场...
- 最简单的composer 包 使用
- 串口IDLE空闲中断+DMA实现接收不定长数据基于stm32cubemx
- 使用 gRPCurl 调试.NET 5的gPRC服务
- API:互联网是如何在幕后工作的?
- 让你事半功倍的小众 Python库
- java 获取项目下的webapp_Spring Boot2 系列教程(一)纯 Java 搭建 SSM 项目
- 数据结构之王道视频中留下的问题
- 通过INI文件实现HYDRA各插件间对象共享
- 10. 在constructors内阻止资源泄露
- dcs系统中数据服务器的冗余,如何提升DCS系统的可靠性?这篇文章讲透了
- raw socket 编程实例
- 环境微生物复习题及答案
- 我不是九爷 带了解 Unity3D与VR虚拟现实
- checkv的基本使用
- Heatmap Plot with ggplot2 【R】
- 如何提取文件名称到excel
- 代码实践:MLP的反向传播算法
- webix, DataTable组件,给表头增加Tooltip