[考试反思]0922csp-s模拟测试50:谜朦
这辈子第5个rank1,是在长期状态低迷再度偶遇傻逼出题人然后总算在下午而不是晚上考了一场试
然后莫名其妙选对了头铁的题把其它暴力打满之后发现sdfz没有参加之后竞争减弱的综合结果。
说是在的其实这套题不很是我的类型,我的分数里面也有一些水分。
T1正解是单调栈但是打飞了,我用大模拟实现了单调的过程,不知道为什么相较于正解,时间快内存小代码复杂度也低。
但是就是有几个细节,吸取之前考试的教训打了个对拍慢慢调。
没看时间,结果花了太多时间(2个小时),看对拍过了就匆忙进T2T3。
T2暴力很好打,轻松拿下了。想到了莫队但是不会证复杂度没有打。
实际上莫队非常优秀。但是面对4维偏序还是犹豫了。
知识迁移。不要怕,要尝试把学过的知识点用到新的题上。
16分钟解决T2暴力之后,看T3,和之前《影子》那道题有关系。
但是其实想的不够好,它基本就是《消防》那题的裸题稍改编,但是没有看出来。
我运用了《影子》那道题的结论(其实应该更早就知道的)然后也码了一个暴力。
惊奇的发现它有60分的暴力分。但是十分不好调,怎么弄怎么弄反正最后终于过了拿下60分。
剩的一点时间里想到一个非正解优化,感觉没什么效果就没有打(估计打不完),就白扔了10分。
然而实际上十分好打。。。3分钟就弄出来了。
能优化一定要优化!!!不要浪费最后的时间!!
这次最好的一点就是没有意外失分。
然而其实有些运气成分。yxm和skyh都压注在T3上了,而我是肝在T1上了,T3的暴力分比T1多,所以我就rank1了。。。
越说越没水准的样子。
但其实我也的确分析了分值分布才这么抉择的,但是我并不知道那两个人没有肝T1。
对分值要有规划。合理分配有限的时间。最浅显的道理:分越多越好。
是状态有所回升吗?
不知道。也许能把之前的坑填上一点。。。
离第一机房线还是有一段不小的距离。。。
不管怎么说,求稳吧,稳中求进。
步调不要乱。继续保持。
DeepinC,加油!
T1:施工
阶梯状的位置不会被拔高,只有平底的坑才会被填。
记录每一个大坑的左右端点,填1单位高度的代价,填1单位高度的代价增长率。
然后扫每一个坑,只要代价还小于等于收益就不断填就好,运用上面的数组可以O(1)计算要填几单位的深度。
填完一个坑之后检查一下看有没有填满,填满的话尝试扩展这个区间看能不能形成一个新的更大的平底坑。
把这个新的平底区间两个端点打上标记,方便其它的坑扩展的时候O(1)吞并这个坑。
大模拟。。。
因为每次填坑至少让坑的大小+1,或者弃坑然后以后再也不碰这个坑,那么就是每次循环会至少让1个位置作废。
所以复杂度是O(n)的。
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int n,h[],l[],r[],top,Rc[],Lc[];long long a[],w[],c,ans;
int main(){//freopen("t1.in","r",stdin);freopen("t1.out","w",stdout);
scanf("%d%lld",&n,&c);
for(int i=;i<=n;++i)scanf("%d",&h[i]);
for(int i=;i<=n;++i)ans+=abs(h[i]-h[i-])*c;
h[]=h[n+]=;
for(int i=;i<=n;++i){
int j=i;
for(;h[j]==h[i];++j);j--;//printf("%d %d %d\n",h[i-1],h[i],h[j+1]);
if(h[i-]>h[i]&&h[i]<h[j+]){
++top;
l[top]=i;r[top]=j;a[top]=j-i+<<;w[top]=j-i+;
}
i=j;
}//printf("%lld\n",ans);
for(int q=;q<=top;++q){//printf("%d %d %lld %lld\n",l[q],r[q],a[q],w[q]);
long long e=c<<;if(l[q]==)e-=c;if(r[q]==n)e-=c;
if(e<w[q])continue;
int t=(e-w[q])/a[q]+;
t=min(t,min(h[r[q]+],h[l[q]-])-h[l[q]]);
h[l[q]]+=t;
if(l[q]!=r[q])h[r[q]]+=t;
ans-=e*t-(w[q]+w[q]+(t-)*a[q])*t/;//printf("%d %lld\n",t,ans);
w[q]+=a[q]*t;
while(h[l[q]]==h[l[q]-]&&!Rc[l[q]-])l[q]--,w[q]++,a[q]+=;
if(h[l[q]]==h[l[q]-])w[q]+=w[Rc[l[q]-]],a[q]+=a[Rc[l[q]-]],l[q]=l[Rc[l[q]-]];
while(h[r[q]]==h[r[q]+]&&!Lc[r[q]+])r[q]++,w[q]++,a[q]+=;
if(h[r[q]]==h[r[q]+])w[q]+=w[Lc[r[q]+]],a[q]+=a[Lc[r[q]+]],r[q]=r[Lc[r[q]+]];
Lc[l[q]]=q;Rc[r[q]]=q;//printf("%d %d %lld %lld\n",l[q],r[q],a[q],w[q]);
if(h[l[q]-]>h[l[q]]&&h[r[q]]<h[r[q]+]){q--;continue;}
}
printf("%lld\n",ans);
}
思路积累:
- 论模拟的重要性。
- 复杂度分析。
T2:蔬菜
正解(?)看大脸,三维容斥树状数组?
不要怂,裸的莫队,只不过是4维罢了,而且每次更新也是O(n)的。
但是就是不会T!!!
就算我把块的大小弄成了1它也不会T。。。(也就是只是排序了一下而已)
开一个桶,随着指针移动改变当前答案和桶里的值就行。
因为是平方,所以每次加入一个元素当前答案的变化量是2x+1或2x-1。
真的很暴力。。。
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
#define P ;
map<int,int>M;
void read(int &p,register char ch=getchar()){p=;
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')p=(p<<)+(p<<)+ch-,ch=getchar();
}
struct qs{
int ord,ans,x1,x2,y1,y2;
#define S 13
friend bool operator<(qs a,qs b){
if(a.x1/S!=b.x1/S)return a.x1/S<b.x1/S;
if(a.y1/S!=b.y1/S)return a.y1/S<b.y1/S;
if(a.x2/S!=b.x2/S)return a.x2/S<b.x2/S;
return a.y2/S<b.y2/S;
}
}q[];
bool com(qs a,qs b){return a.ord<b.ord;}
int n,m,Q,buc[],x[][],nw,cnt,px1,px2,py1,py2;
int main(){//freopen("t2.in","r",stdin);//freopen("t2.out","w",stdout);
read(n);read(m);read(Q);
for(int i=;i<=n;++i)for(int j=;j<=m;++j)read(x[i][j]);
for(int i=;i<=Q;++i)read(q[i].x1),read(q[i].y1),read(q[i].x2),read(q[i].y2),q[i].ord=i;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)if(M.find(x[i][j])==M.end())M[x[i][j]]=++cnt;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)x[i][j]=M[x[i][j]];
sort(q+,q++Q);
buc[x[][]]=px1=px2=py1=py2=nw=;
for(int k=;k<=Q;++k){//printf("Q:%d %d %d %d\n",q[k].x1,q[k].y1,q[k].x2,q[k].y2);
while(px2<q[k].x2){
px2++;
for(int i=py1;i<=py2;++i)nw+=*buc[x[px2][i]]+,buc[x[px2][i]]++;
}
while(py2<q[k].y2){
py2++;
for(int i=px1;i<=px2;++i)nw+=*buc[x[i][py2]]+,buc[x[i][py2]]++;
}
while(px1>q[k].x1){
px1--;
for(int i=py1;i<=py2;++i)nw+=*buc[x[px1][i]]+,buc[x[px1][i]]++;
}P
while(py1>q[k].y1){
py1--;
for(int i=px1;i<=px2;++i)nw+=*buc[x[i][py1]]+,buc[x[i][py1]]++;
}P
while(px2>q[k].x2){
for(int i=py1;i<=py2;++i)nw-=*buc[x[px2][i]]-,buc[x[px2][i]]--;
px2--;
}P while(py2>q[k].y2){
for(int i=px1;i<=px2;++i)nw-=*buc[x[i][py2]]-,buc[x[i][py2]]--;
py2--;
}P
while(px1<q[k].x1){
for(int i=py1;i<=py2;++i)nw-=*buc[x[px1][i]]-,buc[x[px1][i]]--;
px1++;
}
while(py1<q[k].y1){
for(int i=px1;i<=px2;++i)nw-=*buc[x[i][py1]]-,buc[x[i][py1]]--;
py1++;
}
q[k].ans=nw;//puts("");
}
sort(q+,q++Q,com);
for(int i=;i<=Q;++i)printf("%d\n",q[i].ans);
}
- 平方性质的运用。
- 数据结构扩展到高维。
T3:联盟
yxm发现了这题的数据里直径唯一。。。
所以我打的其实不是正解(但是差的也不多了,犯懒了而已)
先假定直径唯一。那就简单了。
我们先求出直径,那么我们砍断的边一定是直径上的边,否则直径仍然存在最长距离没有变。
那么我们就看直径这条链就好了。
然后就好象是《消防》裸题了(《算法竞赛进阶指南》P367《树网的核》)。
从链上正反各跑一遍找到子树最长支链(就是与直径无重边的链),然后就可以求出正反向的子树直径了。
然后就是一个dp了?枚举砍直径上的那一条边,然后看它两个端点的子树直径。
最优决策是把两个直径的中点相连,答案是((1+d1)/2+(1+d2)/2+1)
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<int>num;
int cnt=,fir[],l[],to[],ban[],sta[];
int mxdp,P,al[],ansP1,ansP2,n,ans=,ind[];
int dp1[],dp2[],far[],ltnx[];
void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
void dfs(int p,int dep){//printf("dfs:%d\n",p);
al[p]=;if(dep>=mxdp)mxdp=dep,P=p;
for(int i=fir[p];i;i=l[i])if(!ban[i]&&!al[to[i]])dfs(to[i],dep+);
}
int DFS(int p,int dep){//printf("DFS:%d\n",p);
int flag=;
al[p]=;if(dep>=mxdp)mxdp=dep,P=p,flag=;
for(int i=fir[p];i;i=l[i])if(!ban[i]&&al[to[i]]!=)if(DFS(to[i],dep+))flag=;
if(flag)sta[dep+]=p;
return flag;
}
void Dfs(int p,int fa,int dep,int bel){
far[bel]=max(far[bel],dep);
for(int i=fir[p];i;i=l[i])if(to[i]!=fa&&!ind[to[i]])Dfs(to[i],p,dep+,bel);
}
int main(){
scanf("%d",&n);
for(int i=,x,y;i<n;++i)scanf("%d%d",&x,&y),link(x,y),link(y,x);
dfs(,);mxdp=;DFS(P,);
for(int i=;i<=n;++i)ind[sta[i]]=,al[i]=;
for(int i=;i<=mxdp+;++i)Dfs(sta[i],,,sta[i]);//,printf("%d ",sta[i]);puts("");
for(int i=;i<=mxdp+;++i)dp1[sta[i]]=max(dp1[sta[i-]],far[sta[i]]+i-);//,printf("%d ",dp1[sta[i]]);puts("");
for(int i=mxdp+;i>=;--i)dp2[sta[i]]=max(dp2[sta[i+]],far[sta[i]]+mxdp+-i);//,printf("%d ",dp2[sta[i]]);puts("");
for(int i=;i<=mxdp;++i)for(int j=fir[sta[i]];j;j=l[j])if(to[j]==sta[i+])ltnx[i]=j>>;
for(int i=;i<=mxdp;++i){
int an=max((dp1[sta[i]]+>>)+(dp2[sta[i+]]+>>)+,max(dp1[sta[i]],dp2[sta[i+]]));//printf("%d\n",an);
if(an<ans)ans=an,num.clear(),num.push_back(ltnx[i]);
else if(an==ans)num.push_back(ltnx[i]);
}
sort(num.begin(),num.end());
for(int i=;i<=n;++i)al[i]=;
ban[num[]<<]=ban[num[]<<|]=;
mxdp=;dfs(,);mxdp=;DFS(P,);ansP1=sta[mxdp+>>];//for(int i=1;i<=mxdp+1;++i)printf("%d ",sta[i]);puts("");
mxdp=;
for(int i=;i<=n;++i)if(!al[i])dfs(i,);mxdp=;DFS(P,);ansP2=sta[mxdp+>>];
printf("%d\n",ans);
printf("%d ",num.size());for(int i=;i<num.size();++i)printf("%d ",num[i]);puts("");
printf("%d %d %d %d\n",to[num[]<<],to[num[]<<|],ansP1,ansP2);
}
思路积累:
- 树的直径的性质。
- 直径上双向枚举子树的dp,复杂度为O(2n)
[考试反思]0922csp-s模拟测试50:谜朦的更多相关文章
- [考试反思]0718 NOIP模拟测试5
最后一个是我...rank#11 rank#1和rank#2被外校大佬包揽了. 啊...考的太烂说话底气不足... 我考场上在干些什么啊!!! 20分钟“切”掉T2,又27分钟“切”掉T1 切什么切, ...
- csps模拟测试50反思
又考崩了,T1一眼秒掉错误思路,然后迅速码完,并码完错误暴力,对拍拍上,以为AC.T2想到了二维莫队,发现是子任务就没去打,一直在想别的,T3最后想到60分打法,没有打完,也没时间暴力,挂掉.T2还有 ...
- [CSP-S模拟测试50]反思+题解
??大部分人都觉得T3是道不可做题去刚T1T2了,于是我就侥幸苟到了前面? 这场考试比较成功的就是快速水掉了T1T2的部分分,1h拿到88分起码为之后硬肝T3上了保险(赛后发现就算T3爆零也能rank ...
- noip模拟测试50
考试过程:开题顺序1,2,3,做T1的时候我想到了要求的东西,就是分成尽量少的段使得每段之和>=k,但是我不会求,就打了个暴力走了,然后看T2,这题我觉得和之前做过的一道题比较像,因为我觉得\( ...
- csp-s模拟测试50(9.22)「施工(单调栈优化DP)」·「蔬菜(二维莫队???)」·「联盟(树上直径)」
改了两天,终于将T1,T3毒瘤题改完了... T1 施工(单调栈优化DP) 考场上只想到了n*hmaxn*hmaxn的DP,用线段树优化一下变成n*hmaxn*log但显然不是正解 正解是很**的单调 ...
- [考试反思]0814NOIP模拟测试21
前两名是外校的240.220.kx和skyh拿到了190的[暴力打满]的好成绩. 我第5是170分,然而160分就是第19了. 在前一晚上刚刚爆炸完毕后,心态格外平稳. 想想前一天晚上的挣扎: 啊啊啊 ...
- [考试反思]0714/0716,NOIP模拟测试3/4
这几天时间比较紧啊(其实只是我效率有点低我在考虑要不要坐到后面去吹空调) 但是不管怎么说,考试反思还是要写的吧. 第三次考试反思没写总感觉缺了点什么,但是题都刷不完... 一进图论看他们刷题好快啊为什 ...
- [考试反思]1109csp-s模拟测试106:撞词
(撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...
- [考试反思]0909csp-s模拟测试41:反典
说在前面:我是反面典型!!!不要学我!!! 说在前面:向rank1某脸学习,不管是什么题都在考试反思后面稍微写一下题解. 这次是真的真的运气好... 这次知识点上还可以,但是答题策略出了问题... 幸 ...
随机推荐
- [Tricks] 为文件夹右键菜单增加 【使用VS Code 打开】
传统的IDE安装之后都会在文件夹的右键菜单中增加如[Open in Visual Studio]或者[Open Folder as IntelliJ IDEA Project]这样的选项 但VS Co ...
- PHP的bcmath编译安装
问题描述:zabbix编译安装时PHP条件检查失败,如下图: 解决办法: 1.PHP自带bcmath扩展模块,可直接进行编译安装. [root@localhost etc]# cd /usr/loca ...
- Android 总结:ContentProvider 的使用
一.概述 ContentProvider:为存储和获取数据提供统一的接口,可以在不同的应用程序之间共享数据. Android内置的许多数据都是使用ContentProvider形式,供开发者调用的 ( ...
- 写mysql语句时tab键与空格键
某网页上复制的一份mysql语句,报错,重写一遍后,好了,对比后,发现, 可以看到在sublime text中,网上复制的缩进是空白的,tab键是横杠,空格键是一个点
- python编程基础之十
分支条件: 单一分支条件:if 条件 : 条件真运行... 双分支条件:if 条件 : 条件真运行else: 条件假运行... 多分支条件:if 条件1 : 条件1真运行elif 条件2 : 条件1假 ...
- .net core运用application/x-www-form-urlencoded发起post请求
通常情况下都是使用 application/json发起post请求,但是有的.net 接口只接收 application/x-www-form-urlencoded 例如: { name:" ...
- 性能测试:Jmeter压测过程中的短信验证码读取
问题背景 现如今国内的大部分软件或者网站应用,普遍流行使用短信业务,比如登录.注册以及特定的业务通知等. 对于这些业务,在使用Jmeter进行性能测试的过程中,就会需要自动获取和填入短信验证码,否则性 ...
- Redis 3.0中文版学习(一)
网址:http://wiki.jikexueyuan.com/project/redis-guide/entry-to-master-a.html http://www.yiibai.com/redi ...
- node.js当中的http模块与url模块的简单介绍
一.http模块的简单介绍 node.js当中的http内置模块可以用于创建http服务器与http客户端. 1.引包 const http = require('http'); 2.创建http服务 ...
- How to Compute The Derivatives (如何求导数)(TBC)
A video by 3Blue1Brown in Bilibili\text{A video by 3Blue1Brown in Bilibili}A video by 3Blue1Brown in ...