[考试反思]1107csp-s模拟测试104: 速度
20分钟能做什么?
不粘排行榜,没意义,第一机房集体重启,我侥幸找回了两个文件才有分。
实际得分应该是70+100+60,第二机房rank1。。。放在第一机房就不知道了
T1:中间值
比较喜欢题解的第二种做法。
考虑分治。现在要求出a[l,r],b[L,R]之内的第k小值。
递归边界:如果k==1,那么就是min(a[l],b[L])。如果一个区间为空,直接返回另一个区间的第k小值。
否则我们在a和b中分别取出一些元素,与k的一半取min,然后比较这个元素
即设t=min(k>>1,r-l+1).
那么我们可以比较a[l+t]与b[L+k-t]。较小的一边就可以排除了,继续递归解决即可。
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,a[],b[];
int read(){
register int p=,nt=;register char ch=getchar();
for(;ch<''||ch>'';ch=getchar())nt=ch=='-';
for(;ch>=''&&ch<='';p=(p<<)+(p<<)+ch-,ch=getchar());
return nt?-p:p;
}
int chk(int l,int r,int L,int R,int k){//printf("%d %d %d %d %d\n",l,r,L,R,k);
if(k==)return min(a[l],b[L]);
if(l>r)return b[L+k-];
if(L>R)return a[l+k-];
int t=min(min(r-l+,R-L+),k>>);
if(a[l+t-]>b[L+t-])return chk(l,r,L+t,R,k-t);
else return chk(l+t,r,L,R,k-t);
}
int main(){
freopen("median.in","r",stdin);freopen("median.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)a[i]=read();
for(int i=;i<=n;++i)b[i]=read();
while(m--){
int opt;scanf("%d",&opt);
if(opt==){
int x=read(),y=read(),z=read();
if(!x)a[y]=z;else b[y]=z;
}else{
int l=read(),r=read(),L=read(),R=read(),cnt;
printf("%d\n",chk(l,r,L,R,R-L+r-l+>>));
}
}
}
T2:最小值
感觉像单调栈,但是单调栈里的值都可能是最优决策。
发现转移值与当前点位置无关,所以直接把转移值放进set。弹栈时删除。
#include<cstdio>
#include<set>
using namespace std;
#define inf -12345678901234567
multiset<long long>S;
long long A,B,C,D,dp[],val[];int n,x[],s[],tp;
long long cal(int x){return A*x*x*x+B*x*x+C*x+D;}
struct Segment_Tree{
long long w[];
void modify(int p,int pos,long long v,int cl=,int cr=n){
if(cl==cr){w[p]=v;return;}
if(pos<=cl+cr>>)modify(p<<,pos,v,cl,cl+cr>>);
else modify(p<<|,pos,v,(cl+cr>>)+,cr);
w[p]=max(w[p<<],w[p<<|]);
}
long long ask(int p,int l,int r,int cl=,int cr=n){
if(l<=cl&&cr<=r)return w[p];
return max(l<=cl+cr>>?ask(p<<,l,r,cl,cl+cr>>):inf,r>cl+cr>>?ask(p<<|,l,r,(cl+cr>>)+,cr):inf);
}
}T;
int main(){
freopen("min.in","r",stdin);freopen("min.out","w",stdout);
scanf("%d%lld%lld%lld%lld",&n,&A,&B,&C,&D);
for(int i=;i<=n;++i)scanf("%d",&x[i]);
for(int i=;i<=n;++i){
while(tp&&x[s[tp]]>x[i])S.erase(S.find(val[tp])),tp--;
s[++tp]=i;val[tp]=T.ask(,s[tp-],i-)+cal(x[i]);S.insert(val[tp]);
dp[i]=*(--S.end());T.modify(,i,dp[i]);
}printf("%lld\n",dp[n]);
}
T3:最大值
写的不是题解思路,稍麻烦,码量较大,思维量较大,较麻烦,常数也稍大(需要zkw+fread+取模优化并且还不能乱开long long才能卡过。。。)
可以发现,因为不包含,所以询问按左端点排序之后,右端点也就单调了。
所以其实可以两个单调指针扫一遍,操作就类似于莫队了。
每个魔法阵内部的各种取值的概率比较好计算,从小到大依次考虑,每个元素的概率就是前面所有项$1-p$的乘积再乘这个取值的p。
对于剩下的概率,还要加入一个0。
关键在于魔法阵之间的影响。
暴力的思路就是把区间内的魔法阵都加入set,然后按照和上面一样的方法依次考虑。
只不过要注意,对于任意一个可能值,它的概率都不会受到他自己来源的魔法阵的影响,需要除去。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mod 1000000007
#define ip(p) (1000000008-p)
int qpow(int b,int t,int a=){for(;t;t>>=,b=b*b%mod)if(t&)a=a*b%mod;return a;}
#define inv(p) qpow(p,mod-2)
struct P{
int w,p,b;
friend bool operator<(P a,P b){return a.w<b.w;}
}p;
struct Q{
int l,r;
friend bool operator<(Q a,Q b){return a.l<b.l;}
}qs[];
vector<P>v[],V[];
multiset<P>S;
int n,m,q,alpos[],ans;
main(){freopen("max.in","r",stdin);freopen("max.out","w",stdout);
scanf("%lld%lld%lld",&n,&m,&q);
for(int i=;i<=m;++i)scanf("%lld%lld%lld",&p.b,&p.w,&p.p),v[p.b].push_back(p);
for(int i=;i<=n;++i){
sort(v[i].begin(),v[i].end());
int rpos=;
for(int j=;j<v[i].size();++j)V[i].push_back((P){v[i][j].w,v[i][j].p*rpos%mod,i}),rpos=rpos*ip(v[i][j].p)%mod;
V[i].push_back((P){,rpos,i});
}
for(int i=;i<=q;++i)scanf("%lld%lld",&qs[i].l,&qs[i].r);
sort(qs+,qs++q);qs[].l=;
for(int i=;i<=q;++i){
for(int j=qs[i-].r+;j<=qs[i].r;++j)for(int k=;k<V[j].size();++k)S.insert(V[j][k]);
for(int j=qs[i-].l;j<qs[i].l;++j)for(int k=;k<V[j].size();++k)S.erase(S.find(V[j][k]));
int rpos=;
for(int j=qs[i].l;j<=qs[i].r;++j)alpos[j]=;
for(set<P>::reverse_iterator it=S.rbegin();it!=S.rend();++it){P It=*it;
rpos=(rpos*inv(alpos[It.b]))%mod;
ans=(ans+rpos*It.p%mod*It.w)%mod;
alpos[It.b]=(mod+alpos[It.b]-It.p)%mod;
rpos=rpos*alpos[It.b]%mod;
}
}printf("%lld\n",ans);
}
60分暴力
考虑线段树维护。离散化,下标为水晶的能量。
为了方便处理(并且保证答案正确),我们要强制所有能量值相等的水晶有固定的先后次序,加一个没有意义的第二关键字来进行排序。
(否则的话,对于一个同一个能量值的水晶,它们互相影响就会导致答案值偏小)
就是不存在A限制了B的同时B也限制了A的情况(自己举个权值相同的例子就好)
然后你依次考虑每一个水晶,它会产生的影响是:来自其它魔法阵的能量值更小及相等的晶石产生贡献的概率要乘上1-p。然后当然要把自己的出现概率累加。
线段树维护区间乘,单点加。并没有区间查询,因为你每次查询都是查的整棵树,及时uodate,最后直接拿1号点的权值就好了。
注意这里的区间乘法是要持续生效的,不只作用于当前值,也就是以后再加入某一个值的时候,还要再乘上以前的乘法标记。
所以采用了标记永久化。
要注意一些地方:一个晶石并不会对来自与同一魔法阵的晶石产生影响,但是乘法标记是区间一起打上的不能区分,所以在进行区间加的时候,还要除以以前来自同一魔法阵所打上的乘法标记。
同时还要再考虑,你区间乘好像是每次都从1到某一个位置,那么来自同一个魔法阵的晶石可能对低位产生了多次影响。
所以在下一个晶石乘的时候,还要把它控制的区间内它之前的一颗晶石产生的影响删除(就是乘逆元)
然后还要考虑从线段树里删除魔法阵。
单点加变减。区间乘变乘逆元。
看起来没有什么问题。但是当你发现需要乘0的时候世界就崩塌了。
区间乘0其实还好说,关键是以后在删除魔法阵时还要消除这个乘0的影响。
乘0的逆元?不存在啊。
所以线段树上还要特殊处理一下乘0的标记。每次乘的时候标记+1,每次乘“0的逆元”时标记-1。
只要有标记存在,就证明这段区间的概率都是0,所以对答案的贡献也就是0。
在代码里我就把“0的逆元”设定为-1了。
然后就是卡常。。。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
int Mod(ll x){return x>=mod?x-mod:x;}
const int L=<<|;
char buffer[L],*S,*Q;
#define getchar() ((S==Q&&(Q=(S=buffer)+fread(buffer,1,L,stdin),S==Q))?EOF:*S++)
const int maxn=+;
int read(){
register int p=;register char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')p=(p<<)+(p<<)+ch-,ch=getchar();
return p;
}
ll qpow(ll b,int t,ll a=){for(;t;t>>=,b=b*b%mod)if(t&)a=a*b%mod;return a;}
struct P{
ll w,p;int b,rk;
friend bool operator<(P a,P b){return a.w<b.w;}
}p;
struct N{
ll w;int ord;
friend bool operator<(N a,N b){return a.w<b.w||(a.w==b.w&&a.ord<b.ord);}
}W[];
ll inv(ll p){return p?qpow(p,mod-):-;}
ll ip(ll p){return (mod+-p)%mod;}
vector<P>v[],V[];
int n,m,q,K,k,l[],r[];ll ans;
struct Segment_Tree{
ll w[],lz[];int NONE[];
int cal(int p){return NONE[p]?:lz[p]*w[p]%mod;}
int bit;
void build(){
for(bit=;bit<=k+;bit<<=);
for(int i=;i<=bit+bit;++i) lz[i]=;
}
void mult(int l,int r,ll v){
for(l+=bit-,r+=bit+;l^r^;){
if(~l&){
if(v>) lz[l^]=lz[l^]*v%mod;
else if(!v)NONE[l^]++;
else NONE[l^]--;
}
if(r&){
if(v>) lz[r^]=lz[r^]*v%mod;
else if(!v)NONE[r^]++;
else NONE[r^]--;
}
l>>=; r>>=;
w[l]=Mod(cal(l<<)+cal(l<<|));
w[r]=Mod(cal(r<<)+cal(r<<|));
}
for(l>>=;l;l>>=) w[l]=Mod(cal(l<<)+cal(l<<|));
}
void add(int p,ll v){
p+=bit; w[p]=(w[p]+v*W[p-bit].w)%mod;
for(p>>=;p;p>>=) w[p]=Mod(cal(p<<)+cal(p<<|));
}
}T;
bool com(P a,P b){return a.w>b.w;}
main(){
freopen("max.in","r",stdin);
freopen("max.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
for(int i=;i<=m;++i)p.b=read(),p.w=read(),p.p=read(),v[p.b].push_back(p);
for(int i=;i<=n;++i){
sort(v[i].begin(),v[i].end());
ll rpos=;
for(int j=;j<v[i].size();++j)V[i].push_back((P){v[i][j].w,v[i][j].p*rpos%mod,i,++K}),rpos=rpos*ip(v[i][j].p)%mod;
V[i].push_back((P){,rpos,i,++K});
}
for(int i=;i<=n;++i)for(int j=;j<V[i].size();++j)W[++k]=(N){V[i][j].w,V[i][j].rk};
sort(W+,W++k);T.build();
for(int i=;i<=n;++i)for(int j=;j<V[i].size();++j)V[i][j].w=lower_bound(W+,W++k,(N){V[i][j].w,V[i][j].rk})-W;
for(int i=;i<=n;++i)sort(V[i].begin(),V[i].end(),com);
for(int i=;i<=q;++i)l[i]=read(),r[i]=read();
l[]=;
for(int i=;i<=q;++i){
for(int j=r[i-]+;j<=r[i];++j){
ll totpos=;
for(int k=;k<V[j].size();++k){
if(V[j][k].p==)continue;
ll TP=totpos;totpos=Mod(totpos+V[j][k].p);
T.mult(,V[j][k].w-,ip(totpos));
if(k)T.mult(,V[j][k].w,inv(ip(TP)));
T.add(V[j][k].w,V[j][k].p);
}
}
for(int j=l[i-];j<l[i];++j){
ll totpos=;
for(int k=;k<V[j].size();++k){
if(V[j][k].p==)continue;
totpos=Mod(totpos+V[j][k].p);
T.mult(,V[j][k].w-,inv(ip(totpos)));
if(k)T.mult(,V[j][k].w-,ip(totpos-V[j][k].p));
T.add(V[j][k].w,mod-V[j][k].p);
}
}
ans=(ans+T.w[]*T.lz[])%mod;
}printf("%lld\n",ans);
}
因为细节实在太多,所以哪个地方不会的话在评论区里问,一个一个细节来讲肯定是说不完的。。。
[考试反思]1107csp-s模拟测试104: 速度的更多相关文章
- [考试反思]0718 NOIP模拟测试5
最后一个是我...rank#11 rank#1和rank#2被外校大佬包揽了. 啊...考的太烂说话底气不足... 我考场上在干些什么啊!!! 20分钟“切”掉T2,又27分钟“切”掉T1 切什么切, ...
- [考试反思]0814NOIP模拟测试21
前两名是外校的240.220.kx和skyh拿到了190的[暴力打满]的好成绩. 我第5是170分,然而160分就是第19了. 在前一晚上刚刚爆炸完毕后,心态格外平稳. 想想前一天晚上的挣扎: 啊啊啊 ...
- [考试反思]1109csp-s模拟测试106:撞词
(撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...
- [考试反思]1003csp-s模拟测试58:沉淀
稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...
- [考试反思]0909csp-s模拟测试41:反典
说在前面:我是反面典型!!!不要学我!!! 说在前面:向rank1某脸学习,不管是什么题都在考试反思后面稍微写一下题解. 这次是真的真的运气好... 这次知识点上还可以,但是答题策略出了问题... 幸 ...
- [考试反思]0729NOIP模拟测试10
安度因:哇哦. 安度因:谢谢你. 第三个rank1不知为什么就来了.迷之二连?也不知道哪里来的rp 连续两次考试数学都占了比较大的比重,所以我非常幸运的得以发挥我的优势(也许是优势吧,反正数学里基本没 ...
- [考试反思]0714/0716,NOIP模拟测试3/4
这几天时间比较紧啊(其实只是我效率有点低我在考虑要不要坐到后面去吹空调) 但是不管怎么说,考试反思还是要写的吧. 第三次考试反思没写总感觉缺了点什么,但是题都刷不完... 一进图论看他们刷题好快啊为什 ...
- [考试反思]0816NOIP模拟测试23
210 210 210 170 还可以.暴力打满就rk4了? 但不管怎么说,总算是在改完题之后理直气壮的写考试反思了. T1是个dp,说水也不太水.(当然某脸只要A掉了一道题就要说那是水题) 我的思路 ...
- [考试反思]0801NOIP模拟测试11
8月开门红. 放假回来果然像是神志不清一样. 但还是要接受这个事实. 嗯,说好听点,并列rank#7. 说难听点,垃圾rank#18. 都不用粘人名就知道我是哪一个吧... 因为图片不能太长,所以就不 ...
随机推荐
- [PHP] php, apache, VS Code安装与配置
1. 下载
- MySql自定义函数-关于保留小数位的特殊需求
背景 昨天,关于价格详情接口又来了一个小需求,而且有点特别.价格显示:改为保留两位小数,没错,就是保留两位小数.大家是不是想说这没啥特别的...数据库都有函数搞定了.例如四舍五入的ROUND(x,d) ...
- 【SQLServer】 查询一个字段里不同值的最新一条记录
查询用户编号为1165的所有数据: ,,,,,) ' order by JianCeID desc 查询用户编号为1165且监测参数为(1,2,7,15,19,20)的最新数据: select * f ...
- echarts地图边界数据的实时获取与应用,省市区县多级联动【附最新geoJson文件下载】
首先,来看下效果图 在线体验地址:https://hxkj.vip/demo/echartsMap/,并提供实时geoJson数据文件下载 echarts官方社区链接地址(可在线编辑):https:/ ...
- MongoDB 走马观花(全面解读篇)
目录 一.简介 二.基本模型 BSON 数据类型 分布式ID 三.操作语法 四.索引 索引特性 索引分类 索引评估.调优 五.集群 分片机制 副本集 六.事务与一致性 一致性 小结 一.简介 Mong ...
- python编程基础之二十一
元组: t1 = () t2 = tuple() 成员访问: t1 =(10,7,12,23) print(t1[0]) #下表访问 连接操作 t1 = (1,2,3) t2 =(4,5,6) t3 ...
- 编程杂谈——std::vector与List<T>的性能比较
昨天在比较完C++中std::vector的两个方法的性能差异并留下记录后--编程杂谈--使用emplace_back取代push_back,今日尝试在C#中测试对应功能的性能. C#中对应std:: ...
- Flask中的flash
一.简单的使用 - 必须要设置秘钥因为flash是基于session -设置:flash('aaa') -取值:get_flashed_message() #从源码我们可以看出get_flashed_ ...
- 关于seaJs合并压缩(gulp-seajs-combine )路径与文件ID匹配问题。
前段时间和有大家介绍过用 gulp-seajs-combine 来打包seaJs文件.大家会发现合并seaJs一个很奇怪的现象,那就是它的 ID和路径匹配原则.使得有些文件已经合并过去了,但还是会提示 ...
- 我家很管事的猫——mycat初步部署实践与问题排查
mycat,阿里出品的mysql中间件,提供读写分离和分库分表方案.项目中主要使用的是其读写分离功能. [如何部署?] 本文只采用并测试了双主从模式,配置看这一篇足矣: https://www.cnb ...