这辈子第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:谜朦的更多相关文章

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

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

  2. csps模拟测试50反思

    又考崩了,T1一眼秒掉错误思路,然后迅速码完,并码完错误暴力,对拍拍上,以为AC.T2想到了二维莫队,发现是子任务就没去打,一直在想别的,T3最后想到60分打法,没有打完,也没时间暴力,挂掉.T2还有 ...

  3. [CSP-S模拟测试50]反思+题解

    ??大部分人都觉得T3是道不可做题去刚T1T2了,于是我就侥幸苟到了前面? 这场考试比较成功的就是快速水掉了T1T2的部分分,1h拿到88分起码为之后硬肝T3上了保险(赛后发现就算T3爆零也能rank ...

  4. noip模拟测试50

    考试过程:开题顺序1,2,3,做T1的时候我想到了要求的东西,就是分成尽量少的段使得每段之和>=k,但是我不会求,就打了个暴力走了,然后看T2,这题我觉得和之前做过的一道题比较像,因为我觉得\( ...

  5. csp-s模拟测试50(9.22)「施工(单调栈优化DP)」·「蔬菜(二维莫队???)」·「联盟(树上直径)」

    改了两天,终于将T1,T3毒瘤题改完了... T1 施工(单调栈优化DP) 考场上只想到了n*hmaxn*hmaxn的DP,用线段树优化一下变成n*hmaxn*log但显然不是正解 正解是很**的单调 ...

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

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

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

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

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

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

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

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

随机推荐

  1. 实战SpringCloud响应式微服务系列教程(第七章)

    本章节继续介绍:Flux和Mono操作符(二) 1.条件操作符 Reactor中常用的条件操作符有defaultIfRmpty.skipUntil.skipWhile.takeUntil和takeWh ...

  2. slf4j+logback&logback.xml

    添加maven依赖 <dependencies> <!--https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> ...

  3. Java 添加、修改、读取、删除PPT备注

    概述 幻灯片中的备注信息是只提供给幻灯片演讲者观看的特定内容,在演讲者放映幻灯片时,备注信息可给演讲者提供讲解思路,起到辅助讲解的作用.本文将通过Java程序来演示如何操作PPT幻灯片中的备注信息,要 ...

  4. 合并果子(STL优先队列)

    STL优先队列:priority_queue 定义:priority_queue<int>q; 从小到大:priority_queue<int,vector<int>,g ...

  5. 《java编程思想》P125-P140(第七章复用类部分)

    1.类的成员默认的是包访问权限.允许包内成员访问 2.super.scrub() 调用基类的scrub方法 3.继承并不是复制基类的接口.当创建了一个导出类(子类)对象时,该对象包含了一个基类的子对象 ...

  6. Unreal Engine 4 系列教程 Part 5:制作简单游戏

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  7. js继承机制的实现

    js继承机制的实现 1. 继承的概念 说明继承的最经典的例子:几何形状.实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边).圆是椭圆的一种,它只有一个焦点.三角形.矩形和五边形 ...

  8. 【C语言笔记】#define与typedef的区别

    1.#define define是预处理指令,在编译时不进行任何检查,只进行简单的替换 宏定义的一般形式为: #define 宏名 字符串 这里所说的字符串是一般意义上的字符序列,不要和C语言中的字符 ...

  9. 实验吧之【因缺思汀的绕过】(group by with rollup的注入利用)

    打开页面,查看源代码,发现存在source.txt(http://ctf5.shiyanbar.com/web/pcat/source.txt),如下: <?php error_reportin ...

  10. Redis 3.0中文版学习(一)

    网址:http://wiki.jikexueyuan.com/project/redis-guide/entry-to-master-a.html http://www.yiibai.com/redi ...