2019.03.19 ZJOI2019模拟赛 解题报告
得分: \(100+10+45=155\)(\(T1\)又是水题,\(T2\)写暴力,\(T3\)大力\(STL\)乱搞)
\(T1\):哈夫曼树
首先,根据题目中给出的式子,可以发现,我们要求的其实就是每种方案下的总代价和。
显然,每个数被选择的总次数应该是相同的。
因此,我们可以设\(f_i\)为在还剩下\(i\)个数时进行操作后,每个数被选择的次数。
则易推得转移方程:
\]
对于这个式子,我们可以这样考虑:
- 由于每一次合并时每个数被选择的次数是可以独立计算的,所以,我们可以直接通过\(\frac{i(i-1)}2*f_{i+1}\)这个式子来计算之前的总贡献。(即上一步每个数被选择的次数乘从上一步到这一步的转移方案数)
- 而当前,这个数被选择的方案数为\(i-1\),即选择包含这个数的位置和其余\(i-1\)个位置中的任意一个位置合并。由于还剩\(i\)个数的方案数共有\(\prod_{j=i+1}^n\frac{j(j-1)}2\)种,因此当前的贡献就是\((i-1)\prod_{j=i+1}^n\frac{j(j-1)}2\)。
还有一点要注意的,就是最后总方案数为\(f_2\)。
然后将\(f_2\)乘上数的总和,就是答案了。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define X 1000000007
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
#define Dec(x,y) ((x-=(y))<0&&(x+=X))
#define XSum(x,y) ((x)+(y)>=X?(x)+(y)-X:(x)+(y))
using namespace std;
int n,a[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
class DpSolver
{
private:
#define S(x) ((1LL*(x)*((x)-1)>>1)%X)
int f[N+5];
public:
I int GetAns()
{
RI i,j,t=1,sum=0;for(i=n;i^1;--i)//枚举状态进行转移
f[i]=XSum(1LL*S(i)*f[i+1]%X,1LL*(i-1)*t%X),t=1LL*S(i)*t%X;
for(i=1;i<=n;++i) Inc(sum,a[i]);return 1LL*f[2]*sum%X;//输出答案
}
}DP;
int main()
{
freopen("huffman.in","r",stdin),freopen("huffman.out","w",stdout);
RI i;for(F.read(n),i=1;i<=n;++i) F.read(a[i]);return printf("%d",DP.GetAns()),0;
}
\(T2\):线段树
首先,可以发现一个比较显然的性质:最后查询的这个数的值肯定是一段连续区间的最大值。
则我们所要做的,就是求出这段区间,然后最大值就很好求了。
考虑对当前询问的数,我们找到在它之前最靠近它且包含它的一个区间,然后再去寻找与这个区间有重叠的其他区间,最后就能扩展成一个很大的区间。
那我们能不能从前往后正着进行一遍这样的过程呢?
显然可以。
我们可以定义\(f1_i\)和\(f2_i\),分别表示满足\(j<i\)且\(L_j\le L_i\le R_j\)的最大\(j\)和满足\(j<i\)且\(L_j\le R_i\le R_j\)的最大\(j\)。
这就相当于分别求出最靠近该区间且与该区间有重叠的左边和右边的区间。
这一过程可以直接用线段树,但因为后面的某些特殊需求,因此需要主席树。
则不难发现,对于第\(i\)个区间,它的答案会受到\(f1_i\)和\(f2_i\)两个区间的影响,而\(f1_i\)和\(f2_i\)又会受到各自的\(f1\)和\(f2\)的影响。
如果我们考虑吧\(f1_i\)和\(f2_i\)分别看作\(i\)的父亲,就可以建出两棵树。
而对于一次询问,我们就可以像前面说的那样,在\([l,r]\)范围内找到在它之前最靠近它且包含它的一个区间(这里就需要使用主席树了),然后在两棵树中分别倍增向上跳,分别找到最远的且大于等于\(l\)的操作,然后就能确定出会影响当前位置的区间范围了。
再就相当于线段树上询问区间最大值了。
代码如下:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define Log 20
#define max(x,y) ((x)>(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,m,a[N+5],b[N+5],ql[N+5],qr[N+5],f1[N+5][Log+5],f2[N+5][Log+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
class ChairmanTree//主席树
{
private:
#define STO l,hl,O[rt].S[0]
#define ORZ hl+1,r,O[rt].S[1]
#define PD(x) (O[x].S[0]&&Gmax(O[O[x].S[0]].V,O[x].V),O[x].S[1]&&Gmax(O[O[x].S[1]].V,O[x].V))
int v,tot,Rt[N+5];struct Il {int V,S[2];}O[N*Log<<2];
I void ins(CI l,CI r,int& rt,CI lst,CI ul,CI ur,CI w)//插入新节点,区间修改,维护最靠近某个节点且包含它的一个区间
{
if(O[rt=++tot]=O[lst],ul<=l&&r<=ur) return
(void)(Gmax(O[rt].V,w),O[rt].S[0]=++tot,O[rt].S[1]=++tot);
PD(rt);RI hl=l+r>>1;ul<=hl&&(ins(STO,O[lst].S[0],ul,ur,w),0),
ur>hl&&(ins(ORZ,O[lst].S[1],ul,ur,w),0);
}
I int qry(CI l,CI r,CI rt,CI x)//询问
{
if(!x||!(l^r)) return O[rt].V;PD(rt);RI hl=l+r>>1,res;
return res=(x<=hl?qry(STO,x):qry(ORZ,x)),max(O[rt].V,res);
}
public:
I void Insert(CI l,CI r,CI w) {++v,ins(1,n,Rt[v],Rt[v-1],l,r,w);}
I int Query(CI t,CI x) {return qry(1,n,Rt[t],x);}
}C;
class SegmentTree//线段树
{
private:
#define STO l,hl,rt<<1
#define ORZ hl+1,r,rt<<1|1
#define PU(x) (V[x]=max(V[x<<1],V[x<<1|1]))
int n,v[N+5],V[N<<2];
I void Build(CI l,CI r,CI rt)//初始化建树
{
if(!(l^r)) return (void)(V[rt]=v[l]);RI hl=l+r>>1;
Build(STO),Build(ORZ),PU(rt);
}
I void upt(RI l,RI r,RI rt,CI x,CI y)//单点修改,这里用了非递归实现
{
RI hl;W(l^r) hl=l+r>>1,x<=hl?(r=hl,rt<<=1):(l=hl+1,(rt<<=1)|=1);
V[rt]=y;W(rt>>=1) PU(rt);
}
I int qry(CI l,CI r,CI rt,CI ql,CI qr)//区间求最大值
{
if(ql<=l&&r<=qr) return V[rt];RI hl=l+r>>1,res=0,t;
return ql<=hl&&(t=qry(STO,ql,qr),Gmax(res,t)),qr>hl&&(t=qry(ORZ,ql,qr),Gmax(res,t)),res;
}
public:
I void Init(CI x,int* s) {for(RI i=1;i<=x;++i) v[i]=s[i];Build(1,n=x,1);}
I void Update(CI x,CI y) {upt(1,n,1,x,y);}
I int Query(CI x,CI y) {return qry(1,n,1,x,y);}
}S;
I void Pre()//初始化
{
RI i,j;for(i=1;i<=m;++i) f1[i][0]=C.Query(i-1,ql[i]),//扫一遍,初始化主席树,同时求出f1与f2
f2[i][0]=C.Query(i-1,qr[i]),C.Insert(ql[i],qr[i],i);
for(j=1;j<=Log;++j) for(i=1;i<=n;++i)//预处理倍增数组
f1[i][j]=f1[f1[i][j-1]][j-1],f2[i][j]=f2[f2[i][j-1]][j-1];
}
int main()
{
freopen("segment.in","r",stdin),freopen("segment.out","w",stdout);
RI Qtot,i,op,x,y,z,fl,fr;for(F.read(n,m,Qtot),i=1;i<=n;++i) F.read(a[i]);//读入数据
for(i=1;i<=m;++i) F.read(ql[i],qr[i]);Pre(),S.Init(n,a);W(Qtot--)//读入数据,预处理
{
if(F.read(op,x,y),op^2) {a[x]=y,S.Update(x,y);continue;}//单点修改
if(F.read(z),(fl=fr=C.Query(y,z))<x) {F.writeln(a[z]);continue;}//求出最靠近当前点且包含当前点的区间,若编号小于x,则直接输出这一位上的值
for(i=Log;~i;--i) f1[fl][i]>=x&&(fl=f1[fl][i]),f2[fr][i]>=x&&(fr=f2[fr][i]);//倍增向上跳,求出对当前位置有影响的区间
F.writeln(S.Query(ql[fl],qr[fr]));//输出答案
}return F.clear(),0;
}
\(T3\):接水问题
\(STL\)大暴力,水了\(45\)分。
不会订正,待补。
2019.03.19 ZJOI2019模拟赛 解题报告的更多相关文章
- 2019.03.16 ZJOI2019模拟赛 解题报告
得分: \(100+27+20=147\)(\(T1\)巨水,\(T2,T3\)只能写暴力分) \(T1\):深邃 比较套路的一眼题,显然是一个二分+贪心,感觉就是\(NOIP2018Day1T3\) ...
- 2019.03.02 ZJOI2019模拟赛 解题报告
得分: \(10+0+40=50\)(\(T1\),\(T3\)只能写大暴力,\(T2\)压根不会) \(T1\):道路建造 应该是一道比较经典的容斥题,可惜比赛时没有看出来. 由于要求最后删一条边或 ...
- 2019.03.09 ZJOI2019模拟赛 解题报告
得分: \(20+0+40=60\)(\(T1\)大暴力,\(T2\)分类讨论写挂,\(T3\)分类讨论\(40\)分) \(T1\):天空碎片 一道神仙数学题,貌似需要两次使用中国剩余定理. 反正不 ...
- 2019.03.13 ZJOI2019模拟赛 解题报告
得分: \(55+12+10=77\)(\(T1\)误认为有可二分性,\(T2\)不小心把\(n\)开了\(char\),\(T3\)直接\(puts("0")\)水\(10\)分 ...
- 2019.03.14 ZJOI2019模拟赛 解题报告
得分: \(100+100+0=200\)(\(T1\)在最后\(2\)分钟写了出来,\(T2\)在最后\(10\)分钟写了出来,反而\(T3\)写了\(4\)个小时爆\(0\)) \(T1\):风王 ...
- 2019.03.15 ZJOI2019模拟赛 解题报告
得分: \(20+45+15=80\)(三题暴力全写挂...) \(T1\):Lyk Love painting 首先,不难想到二分答案然后\(DP\)验证. 设当前需验证的答案为\(x\),则一个暴 ...
- 10.30 NFLS-NOIP模拟赛 解题报告
总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没 ...
- 20201101gryz模拟赛解题报告
写在前面 2020rp++ 停课的第一场模拟赛 拿上一年的上一年的day1来考的, 结果得分期望220pts,实际135pts,rank3,太菜了 考着考着机房灯突然灭了,当时慌的一批 以为断电代码要 ...
- 2018.10.26NOIP模拟赛解题报告
心路历程 预计得分:\(100 + 100 + 70\) 实际得分:\(40 + 100 + 70\) 妈妈我又挂分了qwq..T1过了大样例就没管,直到临考试结束前\(10min\)才发现大样例是假 ...
随机推荐
- PIE SDK K-Means分类
1.算法功能简介 K-Means 算法的基本思想是:以空间中 k 个点为中心进行聚类,对最靠近他们的对象归类.通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果. 算法首先随机从数据集中选 ...
- rancher 2.X 搭建小型web集群+mysql主从复制
一,环境配置 rancher 2.1.6 二,配置harbor私有仓库 见上文 三,配置私有镜像 01,总文件 dockerfile 为主配置文件,html 为站点文件wordpress.,官网 ...
- 网页引用Font Awesome图标
问题:最近在IIS上部署web项目的时候,发现浏览器总是报找不到woff.woff2字体的错误.导致浏览器加载字体报404错误,白白消耗了100-200毫秒的加载时间. 原因:因为服务器IIS不认SV ...
- 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响
不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 ...
- ife task0003学习笔记(四):JavaScript构造函数
JavaScript创建对象主要是3种方法:工厂模式.构造函数模式.原型模式.其实对于构造函数的概念,我们并不陌生.在之前学习c++语言的时候,也有提到过构造函数的概念.除了创建对象,构造函数(con ...
- Java动态性 字节码操作
Java动态性的两种常见方式:-字节码操作 - 反射;字节码操作比反射开销小,性能高,JAVAasist性能高于反射,低于ASM 运行时操作字节码可是实现 : 动态生成新的类:动态的改变某个类的结构 ...
- The Definitive C++ Book Guide and List--reference
http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list Reference Style - All ...
- 【转】常用的邮箱服务器(SMTP、POP3)地址、端口
gmail(google.com)POP3服务器地址:pop.gmail.com(SSL启用 端口:995)SMTP服务器地址:smtp.gmail.com(SSL启用 端口:587) 21cn.co ...
- 用ping命令简单的测试 延时、抖动、丢包率
在DOS命令状态下输入 :ping 202.105.135.211 -t (连续的对该IP地址执行Ping命令,直到被用户以Ctrl+C中断)就会得到下面的结果:Pinging 202.105.135 ...
- 深入理解JavaScript系列(19):求值策略(Evaluation strategy)
介绍 本章,我们将讲解在ECMAScript向函数function传递参数的策略. 计算机科学里对这种策略一般称为“evaluation strategy”(大叔注:有的人说翻译成求值策略,有的人翻译 ...