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: 速度的更多相关文章

  1. [考试反思]0718 NOIP模拟测试5

    最后一个是我...rank#11 rank#1和rank#2被外校大佬包揽了. 啊...考的太烂说话底气不足... 我考场上在干些什么啊!!! 20分钟“切”掉T2,又27分钟“切”掉T1 切什么切, ...

  2. [考试反思]0814NOIP模拟测试21

    前两名是外校的240.220.kx和skyh拿到了190的[暴力打满]的好成绩. 我第5是170分,然而160分就是第19了. 在前一晚上刚刚爆炸完毕后,心态格外平稳. 想想前一天晚上的挣扎: 啊啊啊 ...

  3. [考试反思]1109csp-s模拟测试106:撞词

    (撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...

  4. [考试反思]1003csp-s模拟测试58:沉淀

    稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...

  5. [考试反思]0909csp-s模拟测试41:反典

    说在前面:我是反面典型!!!不要学我!!! 说在前面:向rank1某脸学习,不管是什么题都在考试反思后面稍微写一下题解. 这次是真的真的运气好... 这次知识点上还可以,但是答题策略出了问题... 幸 ...

  6. [考试反思]0729NOIP模拟测试10

    安度因:哇哦. 安度因:谢谢你. 第三个rank1不知为什么就来了.迷之二连?也不知道哪里来的rp 连续两次考试数学都占了比较大的比重,所以我非常幸运的得以发挥我的优势(也许是优势吧,反正数学里基本没 ...

  7. [考试反思]0714/0716,NOIP模拟测试3/4

    这几天时间比较紧啊(其实只是我效率有点低我在考虑要不要坐到后面去吹空调) 但是不管怎么说,考试反思还是要写的吧. 第三次考试反思没写总感觉缺了点什么,但是题都刷不完... 一进图论看他们刷题好快啊为什 ...

  8. [考试反思]0816NOIP模拟测试23

    210 210 210 170 还可以.暴力打满就rk4了? 但不管怎么说,总算是在改完题之后理直气壮的写考试反思了. T1是个dp,说水也不太水.(当然某脸只要A掉了一道题就要说那是水题) 我的思路 ...

  9. [考试反思]0801NOIP模拟测试11

    8月开门红. 放假回来果然像是神志不清一样. 但还是要接受这个事实. 嗯,说好听点,并列rank#7. 说难听点,垃圾rank#18. 都不用粘人名就知道我是哪一个吧... 因为图片不能太长,所以就不 ...

随机推荐

  1. Java 学习笔记之 Daemon线程

    Daemon线程: 线程: 用户线程 守护线程 守护线程是一种特殊的线程,在进程中不存在非守护线程了,则守护线程自动销毁. public class DaemonThread extends Thre ...

  2. selenium-webdriver中的显式等待与隐式等待

    在selenium-webdriver中等待的方式简单可以概括为三种: 1 导入time包,调用time.sleep()的方法传入时间,这种方式也叫强制等待,固定死等一个时间 2 隐式等待,直接调用i ...

  3. Label的作用是什么,是怎么用的?

    label标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到标签相关的表单控件上. 如: <form> <label for="male"&g ...

  4. Linux虚拟机中配置JDK环境变量(Ubuntu系统)

    首先通过Xshell中文件传输想你的虚拟机上传你的jdk,如图所示:(需要本机安装Xftp:链接: https://pan.baidu.com/s/1sWHmywZ2C6V2n4aa1FqqFg 提取 ...

  5. JVM Java字节码的角度分析switch的实现

    目录 Java字节码的角度分析switch的实现 引子 前置知识 一个妥协而又枯燥的方案 switch的实现 回顾历史 字节码分析 其他实现方式? Java字节码的角度分析switch的实现 作者 k ...

  6. 非后端开发Mysql日常使用小结

    数据库的五个概念 数据库服务器 数据库 数据表 数据字段 数据行 那么这里下面既是对上面几个概念进行基本的日常操作. 数据库引擎使用 这里仅仅只介绍常用的两种引擎,而InnoDB是从MySQL 5.6 ...

  7. Redis 介绍学习

    1.Redis 简介 Redis 是一个支持数据结构更多的键值对数据库.它的值不仅可以是字符串等基本数据 类型,也可以是类对象,更可以是 Set.List.计数器等高级的数据结构. Memcached ...

  8. 从零开始的vue学习笔记(八)

    前言 今天花一天时间阅读完Vue Router的官方文档的基础部分,简单的做一下总结和记录 Vue Router是什么 Vue Router 是 Vue.js 官方的路由管理器,用于构建单页应用(SP ...

  9. python selenium单/复选框操作

    一.单选:radio 1.首先是定位选择框的位置 2.定位id,点击图标就可以了,代码如下(获取url地址方法:把上面源码粘贴到文本保存为.html后缀后用浏览器打开,在浏览器url地址栏复制出地址就 ...

  10. 在SRAM、FLASH中调试代码的配置方法(附详细步骤)

    因为STM32的FLASH擦写次数有限(大概为1万次),所以为了延长FLASH的使用时间,我们平时调试时可以选择在SRAM中进行硬件调试.除此之外,SRAM 存储器的写入速度比在内部 FLASH 中要 ...