【四校联考】【比赛题解】FJ NOIP 四校联考 2017 Round 7
此次比赛为厦门一中出题。都是聚劳,不敢恭维。
莫名爆了个0,究其原因,竟然是快读炸了……很狗,很难受。
话不多说,来看看题:
【T1】
题意:
样例:
PS:1<=h[i]<=100000。
题解:
假设\(max\left(h_{i}\right)=M\),可以发现最大高度不超过\(M+n\)。
而用\(m\)块砖,向上最多能搭\(\sqrt{m}\)个。
故最大高度为\(M+min\left(n,\sqrt{m}\right)\)。
而最低高度为\(M\)(或\(M+1\))。
也就是说,高度的范围不超过3163。
而可以看出对于高度\(h\),能否搭建起高\(h\)的塔是单调的。
如果我们二分高度\(h\),计算能否搭建,就能够较快出解。
考虑在第\(i\)列搭上\(h\)的高度,那么最少需要多少砖块呢?
当然是按照金字塔形斜向下,直到遇到第一个可以作为支撑的砖块。
设\(left\left[i\right]\left[h\right]\)为坐标\(\left(i,h\right)\)向左斜向下遇到的第一个砖块的标号,\(right\left[i\right]\left[h\right]\)则为向右斜向下,若不存在,则值为0。
那么最少需要的砖块数(包括已经搭建的)等于:
\(Sum[i][h]=h(right[i][h]-left[i][h]-1)-\frac{(i-left[i][h])(i-left[i][h]-1)}{2}-\frac{(right[i][h]-i)(right[i][h]-i-1)}{2}\)。
而需要多搭的为:\(Sum[i][h]-(sum_{right[i][h]-1}-sum_{left[i][h]})\),其中\(sum\)为前缀和。
现在,如何快速算出\(left\)和\(right\)呢?
看往左斜向下的,容易发现,\(k\)能够阻挡\((i,h)\)当且仅当\(h_{k}-k\geqslant h-i\)。
而对于向右下方的,我们有,\(k\)能够阻挡\((i,h)\)当且仅当\(h_{k}+k\geqslant h+i\)。
考虑记录下\(L_{k}=h_{k}-k\)与\(R_{k}=h_{k}+k\)。
那么我们就是对特定\(i,h\)要求出从右往左第一个\(k\)使得\(L_{k}\geqslant h-i\),求出从左往右第一个\(k\)使得\(R_{k}\geqslant h+i\)。
这是单调栈的模型,先把\(L_{k}\)和\(R_{k}\)用单调栈维护一遍。
而在计算过程中,\(h+i\)与\(h-i\)是单调递增或递减的,这有了双指针扫描的可能性。
这就是整体思路,代码有点复杂……
#include<cstdio>
#define F(i,a,b) for(int i=a;i<=b;++i)
#define dF(i,a,b) for(int i=a;i>=b;--i)
int n,m,h[],Ans,M;
long long sum[];
int left[][],lp,right[][],rp;
int L[],R[];
inline int Max(int x,int y){return x>y?x:y;}
void init(){
scanf("%d%d",&n,&m);
F(i,,n) scanf("%d",h+i), M=Max(M,h[i]);
F(i,,n) sum[i]=sum[i-]+h[i];
lp=;
F(i,,n){
while(lp&&left[lp][]<=h[i]-i) --lp;
left[++lp][]=h[i]-i;
left[lp][]=i;
} left[][]=;
rp=;
dF(i,n,){
while(rp&&right[rp][]<=h[i]+i) --rp;
right[++rp][]=h[i]+i;
right[rp][]=i;
} right[][]=;
// F(i,1,lp) printf("(%d,%d) ",left[i][0],left[i][1]); puts("");
// F(i,1,rp) printf("(%d,%d) ",right[i][0],right[i][1]); puts("");
Ans=M;
}
int main(){
freopen("block.in","r",stdin);
freopen("block.out","w",stdout);
init();
int l=M+, r=M+, mid, ok;
while(l<=r){
mid=(l+r)>>;
ok=;
// printf("%d:\n",mid);
for(int i=,pos=;i<=n;++i){
L[i]=;
if(pos!=lp&&left[pos+][]>=mid-i) ++pos;
if(left[pos][]>=mid-i) L[i]=left[pos][]+;
}
// for(int i=1;i<=n;++i) printf("%d ",L[i]); puts("");
for(int i=n,pos=;i>=;--i){
R[i]=;
if(pos&&right[pos+][]>=mid+i) ++pos;
if(right[pos][]>=mid+i) R[i]=right[pos][]-;
}
// for(int i=1;i<=n;++i) printf("%d ",R[i]); puts("");
F(i,,n){
if(L[i]==||R[i]==) continue;
long long Sum=
(long long)mid*(R[i]-L[i]+)-
(long long)(i-L[i]+)*(i-L[i])/-
(long long)(R[i]-i+)*(R[i]-i)/-
(sum[R[i]]-sum[L[i]-]);
// printf("%d:%lld ",i,Sum);
if(Sum<=m) {ok=; break;}
}//puts("");
if(ok) l=mid+, Ans=mid;
else r=mid-;
}
printf("%d",Ans);
return ;
}
【T2】
题意:
样例:
题解:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
// head const int N=;
int n,m,cnt0[N],cnt1[N];
ll m0,md,cnt2[N];
int main() {
freopen("cake.in","r",stdin);
freopen("cake.out","w",stdout);
scanf("%d%d",&m,&n);
scanf("%lld%lld",&m0,&md);
rep(i,,m+) {
// printf("%lld\n",m0);
cnt0[m0]++;
m0=(m0*+md)%(n+);
}
// puts("");
scanf("%lld%lld",&m0,&md);
rep(i,,n+) {
// printf("%lld\n",m0);
cnt1[m0]++; cnt2[m0]+=m0;
m0=(m0*+md)%(m+);
}
int x=; ll sx=;
rep(i,,m+) cnt1[i]+=cnt1[i-],cnt2[i]+=cnt2[i-];
ll ans=cnt2[m];
// puts("");
rep(i,,n+) {
rep(j,,cnt0[i]) {
x++; sx+=i;
int y=cnt1[m-x];
assert(x<=m&&y<=n);
ll ret=(ll)(m-x)*(n-y)+cnt2[m-x]+sx;
// printf("%lld\n",ret);
ans=min(ans,ret);
}
}
printf("%lld\n",ans);
}
【T3】
题意:
题解:
我个人不会做……有待学习。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define Rep(i,x) for(int i=head[x];i+1;i=nxt[i])
#define pb push_back
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=4e6+;
const int M=8e6+;
inline void read(int &x){x=;char ch=getchar(); while(ch<'') ch=getchar(); while(ch>=''){x=x*+ch-;ch=getchar();}}
inline void judge()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
}
int fa[N],head[N],nxt[M],to[M],e,w[M],id[M];
int wod[N];
int son[N][],pd[N],tp[N];
inline void init(){memset(head,-,sizeof(head)); e=;}
inline void add_edge(int x,int y,int z,int ii){to[e]=y;w[e]=z;nxt[e]=head[x];id[e]=ii;head[x]=e++;}
ll ma[N][],ans[N][];
inline void Insert(int x,ll y,int cjl,int ii)
{
if(ma[x][]<y){ma[x][]=ma[x][];ma[x][]=y;son[x][]=son[x][];son[x][]=cjl;pd[x]=ii;}
else if(y>ma[x][]){ma[x][]=y;son[x][]=cjl;}
}
void dfs(int x)
{
ma[x][]=ma[x][]=;Rep(i,x)
{
int j=to[i]; if(j==fa[x]) continue; fa[j]=x; tp[j]=id[i];
dfs(j); Insert(x,ma[j][]+(ll)w[i],j,tp[j]);
}
}
inline void Insert3(int x,ll y)
{
if(ma[x][]<y){ma[x][]=ma[x][];ma[x][]=y;}
else if(y>ma[x][])ma[x][]=y;
}
void dfs3(int x,int f,int pp)
{
ma[x][]=ma[x][]=;ans[pp][]=;Rep(i,x)
{
int j=to[i]; if(j==f) continue;
dfs3(j,x,id[i]); Insert3(x,ma[j][]+(ll)w[i]);
ans[pp][]=max(ans[pp][],ans[id[i]][]);
}ans[pp][]=max(ans[pp][],ma[x][]+ma[x][]);
}
vector<int> tt,Route,Rid,tt2;
void dfs2(int x)
{
tt.push_back(x); if(pd[x])tt2.push_back(pd[x]);
if(son[x][]) dfs2(son[x][]);
else return;
}
ll md[N];
int main()
{
judge();
int n;read(n);init();rep(i,,n-)
{
int x,y,z;read(x);read(y);read(z);
add_edge(x,y,z,i);add_edge(y,x,z,i);
wod[i]=z;
}fa[]=;dfs();int mj=;rep(i,,n) if(ma[i][]+ma[i][]>ma[mj][]+ma[mj][]) mj=i;
rep(i,,n-) ans[i][]=ma[mj][]+ma[mj][];
if(son[mj][])
{
dfs2(son[mj][]); for(int i=(int)tt.size()-;i>=;i--) Route.pb(tt[i]);
for(int i=(int)tt2.size()-;i>=;i--) Rid.pb(tt2[i]); tt2.clear();tt.clear();
Rid.pb(tp[son[mj][]]);
}
Route.pb(mj);
if(son[mj][])
{
Rid.pb(tp[son[mj][]]);
dfs2(son[mj][]); for(int i=;i<(int)tt.size();i++) Route.pb(tt[i]);
for(int i=;i<(int)tt2.size();i++) Rid.pb(tt2[i]);
}
int sz=Route.size();memset(ma,,sizeof(ma));
ll pre=;ll maa=;
rep(i,,sz-)
{
int j=Route[i];
Rep(xjt,j)
{
if(i && to[xjt]==Route[i-]) continue;
if(i<sz- && to[xjt]==Route[i+]) continue;
dfs3(to[xjt],j,id[xjt]); md[i]=max(md[i],w[xjt]+ma[to[xjt]][]);
}
maa=max(maa,md[i]+pre);if(i!=sz-)ans[Rid[i]][]=maa;
if(i!=sz-) pre+=wod[Rid[i]];
}
pre=; maa=;memset(md,,sizeof(md));
per(i,sz-,)
{
int j=Route[i];
Rep(xjt,j)
{
if(i && to[xjt]==Route[i-]) continue;
if(i<sz- && to[xjt]==Route[i+]) continue;
dfs3(to[xjt],j,id[xjt]); md[i]=max(md[i],w[xjt]+ma[to[xjt]][]);
}
maa=max(maa,md[i]+pre);if(i)ans[Rid[i-]][]=maa;
if(i) pre+=wod[Rid[i-]];
}
rep(i,,n-) if(ans[i][]>ans[i][]) swap(ans[i][],ans[i][]);
ll solo=;
rep(i,,n-)
{
solo+=ans[i][]*23333ll+ans[i][]*2333ll+233ll*(ll)i*(ll)i+23ll*(ll)i+2ll;
//cerr<<ans[i][1]<<' '<<ans[i][0]<<endl;
solo%=2333333333333333ll;
}
printf("%lld\n",solo);
return ;
}
【四校联考】【比赛题解】FJ NOIP 四校联考 2017 Round 7的更多相关文章
- 纪中OJ 2019.02.15【NOIP提高组】模拟 B 组 梦回三国 比赛题解(第一个)
声明 旁边的同学小 H(胡)对我说: “哟,比赛拿了 140,强!要知道,如果哥第三题 AC 了,哥就 230 了,你个废柴!!!(比赛实际分数 130 额呵)” 顿时,千万草泥马从我心中奔腾而过:你 ...
- [比赛题解]CWOI2019-1
[比赛题解]CWOI2019-1 比赛日期:2019.10.12 T1 一道神仙DP题. 我们考虑\(dp[i][j][k]\)表示最后\(i\)位数,\(i-1\)位都是9,最后一位为\(j\),最 ...
- 洛谷P2460 [SDOI2007]科比的比赛(题解)(贪心+搜索)
科比的比赛(题解)(贪心+搜索) 标签:算法--贪心 阅读体验:https://zybuluo.com/Junlier/note/1301158 贪心+搜索 洛谷题目:P2460 [SDOI2007] ...
- 几校联考——day1题解
T1 约数的个数(好像不可提交) 如果一个整数a能够整除整数b,那么a叫做b的约数.现在有N(1 <= N <= 100,000)个整数,对于其中的每一个数,请找出它在其余N - 1个整数 ...
- 【简】题解 P5283 [十二省联考2019]异或粽子
传送门:P5283 [十二省联考2019]异或粽子 题目大意: 给一个长度为n的数列,找到异或和为前k大的区间,并求出这些区间的异或和的代数和. QWQ: 考试时想到了前缀异或 想到了对每个数按二进制 ...
- 福建工程学院第十四届ACM校赛M题题解 fwt进阶,手推三进制fwt
第九集,结束亦是开始 题意: 大致意思就是给你n个3进制的数字,让你计算有多少对数字的哈夫曼距离等于i(0<=i<=2^m) 思路: 这个是一个防ak题,做法是要手推公式的fwt 大概就这 ...
- 福建工程学院第十四届ACM校赛J题题解
第六集,想不到你这个浓眉大眼的都叛变革命了 题意: 给你两个只包含01的字符串S和T,问你在允许一次错误的情况下,T是否能成为S的子串 思路: 这个问题的解法挺多,我是用fft匹配的,也比较简单,针对 ...
- 福建工程学院第十四届ACM校赛G题题解
外传:编剧说了不玩游戏不行 题意: 有n个石堆,我每次只能从某一堆中取偶数个石子,你取奇数个,我先手,先不能操作的人输.问最后谁能赢. 思路: 这个题仔细想想,就发现,取奇数的人有巨大的优势,因为假设 ...
- 福建工程学院第十四届ACM校赛B题题解
第二集,未来的我发量这么捉急的吗 题意: 有n个数,请问有多少对数字(i,j)(1<=i<j<=n),满足(a[i]^a[j])+((a[i]&a[j])<<1) ...
随机推荐
- sqlserver中where条件加判断
我想实现如下功能: where case when (@a = null) then 1 = 1 else @a=a and b=@b 但是这样报错,经过翻阅资料找到如下解决方案: where (1 ...
- 【开发工具IDE】eclipse的SVN提交忽略target等多余文件
这个build失败的解决方案就是不要把你项目的 target目录放在src repository 里面,还有 .project 和 .classpath最好也别放到src repository 里. ...
- BZOJ3157/BZOJ3516 国王奇遇记(矩阵快速幂/数学)
由二项式定理,(m+1)k=ΣC(k,i)*mi.由此可以构造矩阵转移,将mi*ik全部塞进去即可,系数即为组合数*m.复杂度O(m3logn),因为大常数喜闻乐见的T掉了. #include< ...
- [UOJ391] 鸽举选仕
我把这题推荐给yyb让他把这题做它的T2他竟然不要QwQ....... 题目大意: 下发八个题目和对应的八份代码,请构造数据Hack下发代码. Task1 下发代码用了一些神奇做法实现A + B = ...
- Java8 新特性Stream 的学习和使用方法
流(Stream) 流是java 8 中新引入的特性,用来处理集合中的数据,Stream 是一个来自数据源的元素队列并支持聚合操作. Java 中 Stream 不会存储元素. 数据源 流的来源. 可 ...
- BZOJ 1013 | 一份写了一堆注释的高斯消元题解
题意 给出\(n\)维直角坐标系中\(n + 1\)个点的坐标,它们都在一个\(n\)维球面上,求球心坐标. 题解 设球面上某两个点坐标为\((a_1, a_2, ... a_n)\)和\((b_1, ...
- 【bzoj3238】 Ahoi2013—差异
http://www.lydsy.com/JudgeOnline/problem.php?id=3238 (题目链接) 题意 给出一个字符串,求${\sum_{1<=i<j<=n} ...
- 20165218 《网络对抗技术》Exp0 Kali安装 Week1
Kali Linux安装 下载 在Kali官网下载Kali Linux 64 Bit版本 打开VM,选择文件->新建虚拟机,一直点击下一步,注意这里选择稍后安装操作系统 版本中找不到Kali,可 ...
- LGP4588[JSOI2018]扫地机器人
题解 需要先说明一点东西: 1 同一副对角线方向相同,共有$gcd(n,m)$条不同的副对角线,机器人的行为是一个$gcd(n,m)$的循环:: 如果左上方是$(1,1)$,容易看出所有的路径是从左或 ...
- python检测服务器是否ping通
好想在2014结束前再赶出个10篇博文来,~(>_<)~,不写博客真不是一个好兆头,至少说明对学习的欲望和对知识的研究都不是那么积极了,如果说这1天的时间我能赶出几篇精致的博文,你们信不信 ...