[考试反思]1105csp-s模拟测试102: 贪婪
还是有点蠢。。。
多测没清空T3挂40。。。(只得了人口普查分20)
多测题要把样例复制粘两遍自测一下防止未清空出锅。
然而不算分。。。
其实到现在了算不算也不重要了吧。。。
而且其实T3只考虑最长路上的点这个思路其实肯定都能想到啊。
懒得打。那么就分少啊。
对于分数,还是要贪婪一些的。
T1:你相信引力吗
维护最大值关系:肉眼可见的单调栈/队列。(刚开始认为是栈,后来其实发现是一个队列)
环,经典套路,拆成两倍长的序列。
维护一个单调不增的单调栈,根据题目含义画画图,可以发现答案是:
对于当前点,从栈里第一个严格大于当前元素的值开始数,栈里有多少个元素。
暴力思路就是二分。
可以发现你找到的那个元素后面的部分都会被弹掉,所以一边弹一边计数即可。
特殊的一点是权值相同的,这部分不会被弹栈,但是对答案也有贡献。
所以在每个元素入栈的时候记录一下栈顶有几个连续相同的元素即可。
然后还要考虑找到第一个比当前元素大的元素,所以检查一下栈底的元素是否比当前元素大,如果大的话再累加1个答案。
然后还要考虑环拉成序列以后同一个位置的元素可能在栈里出现2次。
所以就不是栈了,是个队列。如果队首元素的下表就是当前的下标,那么就弹出。
弹出的时候要考虑它对“栈里连续相同元素数量”的影响。
还有一个问题,如果对于一对冰锥,它的优弧和劣弧都满足条件,那么它的答案会被计算两次。
如果最大值出现了k次,那么它对答案产生的多出的贡献就是$\frac{k(k-1)}{2}$
特别的,当k=1时,如果次大值出现了j次,那么多出的答案就是$j$
所以把多出的贡献减去就是最终答案。
细节较多。但是如果上述分类讨论都注意到了的话调试还是挺简单的。
#include<cstdio>
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;
}
int n,a[],q[],p[],s[],h=,t,mx,se,tmx,tse;long long ans;
int main(){
freopen("jolyne.in","r",stdin);freopen("jolyne.out","w",stdout);
n=read();
for(int i=;i<=n;++i)a[i]=read();
for(int i=;i<=n;++i)
if(a[i]>mx)se=mx,tse=tmx,mx=a[i],tmx=;
else if(a[i]==mx)tmx++;
else if(a[i]>se)se=a[i],tse=;
else if(a[i]==se)tse++;
for(int i=;i<=n;++i){
while(t>=h&&a[i]>q[t])t--;
if(t>=h&&q[t]==a[i])s[++t]=s[t-]+;else s[++t]=;
q[t]=a[i];p[t]=i;
}
for(int i=;i<=n;++i){int nt=;
while(t>=h&&p[h]<=i)nt=a[i]==q[h],h++;
while(t>=h&&a[i]>q[t])t--,ans++;
if(t>=h&&q[t]==a[i])s[++t]=s[t-]+;else s[++t]=;
q[t]=a[i];p[t]=n+i;
if(h==t||q[h]!=q[t])nt=;
s[t]-=nt;ans+=s[t]-;if(q[h]!=a[i])ans++;
// for(int j=h;j<=t;++j)printf("%3d ",q[j]);puts("");
// for(int j=h;j<=t;++j)printf("%3d ",s[j]);puts("");
// printf("%lld\n",ans);
}
if(tmx==)ans-=tse;
else ans-=tmx*(tmx-1ll)/;
printf("%lld\n",ans);
}
T2:停不下来的团长奥尔加
比较明显的线性递推。
可以根据每个点的出度/入度平衡来做。
出度分为去右边的和去左边的,入度也是。
然后就可以递推了。
#include<cstdio>
#define mod 1000000007
int n,to[];long long ans,oR[],oL[],iL[],iR[];
int main(){
freopen("rideon.in","r",stdin);
freopen("rideon.out","w",stdout);
scanf("%d",&n);
for(int i=;i<=n;++i)scanf("%d",&to[i]);
iL[n+]=;
for(int i=n;i;--i){
oR[i]=iL[i+];
oL[i]=oR[i];
iR[to[i]]=(iR[to[i]]+oL[i])%mod;
iL[i]=(oR[i]+oL[i]-iR[i]+mod)%mod;
ans=(ans+iL[i]+iR[i])%mod;
}printf("%lld\n",ans);
}
T3:Lesson5!
这题为什么要多测啊啊啊?一定要记得清空不然调到死。
建超级源汇会好做一些。(不建也可以,区别不大)
先预处理出来源点到每个点的距离f,以及每个点到汇点的距离g。
正反拓扑得到。
然后对于每一条边,经过它的最长路是fx+gy+1。称之为边的权值。
对于删除一个点,那么所有与它有关的边都不能贡献答案。
所以再一个正向拓扑,分层考虑所有点。
对于每一个点,删除所有入边的权值的贡献(就是从数据结构里删除),此时出边的贡献还没有统计。
所谓的贡献答案,其实就是在所有可行的最长路中取出最大的那一个,是一个维护了多个最长路决策的数据结构。
(所以说题解说的好像多么玄乎一样)
先不考虑这个数据结构是什么,假设我们能应付它需要的所有操作。
所以其实当前的状态下,就相当与删除了这个点时的状态,所以此时的最长路就是删掉这个点的最长路。(就是从数据结构里找到最大值)
这个点考虑完之后就可以把它的出边都贡献答案了。(就是放入数据结构)
因为你会在进入这一层的时候删除,走出这一层的时候加入,那么其实它只会在本层到下一层的时间存在。
进入下一层的时候代表这条最长路的边就不再是这一条了而是在这条最长路上的下一条。所以一定会不重不漏的最优决策。
怎么求出答案?需要一个可以求最大值,可以删除的数据结构。
multiset。(于是我开始嘲笑出题人不会STL还要写权值线段树)
然后我被卡常了。。。
但是我坚决不打数据结构!所以就上priority_queue乱搞。
加一个懒惰删除即可。
不建立超级源汇的话,根据含义考虑,其实少的边就是从每一个点到其汇点的贡献,所以在拓扑开始之前直接把每个点到它的汇点的答案放进数据结构里就好了。
还有我感觉mikufun的思路很好,附个链接(虽然skyh没脸又爆跳父亲AC了然后才开始长脸重新改了一遍(再长脸脸该多大了啊。。。))
#include<bits/stdc++.h>
using namespace std;
priority_queue<int>Q;
vector<int>v[];
int n,m,dp[],ans,ansp,cnt,fir[],l[],to[],deg[];
int f[],g[],q[],X[],Y[],delcnt[];
void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;deg[b]++;}
int main(){
freopen("johnny.in","r",stdin);
freopen("johnny.out","w",stdout);
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=;i<=n+;++i)fir[i]=f[i]=g[i]=,v[i].clear();
while(!Q.empty())Q.pop();
ans=;cnt=;
for(int i=;i<=m;++i)scanf("%d%d",&X[i],&Y[i]),link(X[i],Y[i]);
for(int i=m+;i<=m+n;++i)X[i]=,Y[i]=i-m,link(X[i],Y[i]);
m+=n;
for(int i=m+;i<=m+n;++i)X[i]=i-m,Y[i]=n+,link(X[i],Y[i]);
m+=n;n++;
int t=;
for(int i=;i<=n;++i)if(!deg[i])q[++t]=i;
for(int h=;h<=t;++h){
int p=q[h];
for(int i=fir[p];i;i=l[i]){
deg[to[i]]--;f[to[i]]=max(f[to[i]],f[p]+);
if(!deg[to[i]])q[++t]=to[i];
}
}
t=;for(int i=;i<=n;++i)fir[i]=;cnt=;
for(int i=;i<=m;++i)link(Y[i],X[i]);
for(int i=;i<=n;++i)if(!deg[i])q[++t]=i;
for(int h=;h<=t;++h){
int p=q[h];
for(int i=fir[p];i;i=l[i]){
deg[to[i]]--;g[to[i]]=max(g[to[i]],g[p]+);
if(!deg[to[i]])q[++t]=to[i];
}
}
t=;for(int i=;i<=n;++i)fir[i]=;cnt=;
for(int i=;i<=m;++i)link(X[i],Y[i]),v[Y[i]].push_back(+g[Y[i]]+f[X[i]]);
for(int i=;i<=n;++i)if(!deg[i])q[++t]=i;
Q.push();
for(int h=;h<=t;++h){
int p=q[h];
for(int i=;i<v[p].size();++i)delcnt[v[p][i]]++;
while(delcnt[Q.top()])delcnt[Q.top()]--,Q.pop();
if(Q.top()<ans&&p&&p!=n)ans=Q.top(),ansp=p;
if(Q.top()==ans&&p<ansp&&p)ansp=p;
for(int i=fir[p];i;i=l[i]){
deg[to[i]]--;Q.push(+f[p]+g[to[i]]);
if(!deg[to[i]])q[++t]=to[i];
}
}
printf("%d %d\n",ansp,ans-);
}
}
60M的读入量没写快读居然也过了。。。
[考试反思]1105csp-s模拟测试102: 贪婪的更多相关文章
- [考试反思]0718 NOIP模拟测试5
最后一个是我...rank#11 rank#1和rank#2被外校大佬包揽了. 啊...考的太烂说话底气不足... 我考场上在干些什么啊!!! 20分钟“切”掉T2,又27分钟“切”掉T1 切什么切, ...
- [考试反思]0814NOIP模拟测试21
前两名是外校的240.220.kx和skyh拿到了190的[暴力打满]的好成绩. 我第5是170分,然而160分就是第19了. 在前一晚上刚刚爆炸完毕后,心态格外平稳. 想想前一天晚上的挣扎: 啊啊啊 ...
- [考试反思]1109csp-s模拟测试106:撞词
(撞哈希了用了模拟测试28的词,所以这次就叫撞词吧) 蓝色的0... 蓝色的0... 都该联赛了还能CE呢... 考试结束前15分钟左右,期望得分300 然后对拍发现T2伪了写了一个能拿90分的垃圾随 ...
- [考试反思]0909csp-s模拟测试41:反典
说在前面:我是反面典型!!!不要学我!!! 说在前面:向rank1某脸学习,不管是什么题都在考试反思后面稍微写一下题解. 这次是真的真的运气好... 这次知识点上还可以,但是答题策略出了问题... 幸 ...
- [考试反思]0729NOIP模拟测试10
安度因:哇哦. 安度因:谢谢你. 第三个rank1不知为什么就来了.迷之二连?也不知道哪里来的rp 连续两次考试数学都占了比较大的比重,所以我非常幸运的得以发挥我的优势(也许是优势吧,反正数学里基本没 ...
- [考试反思]0714/0716,NOIP模拟测试3/4
这几天时间比较紧啊(其实只是我效率有点低我在考虑要不要坐到后面去吹空调) 但是不管怎么说,考试反思还是要写的吧. 第三次考试反思没写总感觉缺了点什么,但是题都刷不完... 一进图论看他们刷题好快啊为什 ...
- [考试反思]1003csp-s模拟测试58:沉淀
稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...
- [考试反思]0816NOIP模拟测试23
210 210 210 170 还可以.暴力打满就rk4了? 但不管怎么说,总算是在改完题之后理直气壮的写考试反思了. T1是个dp,说水也不太水.(当然某脸只要A掉了一道题就要说那是水题) 我的思路 ...
- [考试反思]0801NOIP模拟测试11
8月开门红. 放假回来果然像是神志不清一样. 但还是要接受这个事实. 嗯,说好听点,并列rank#7. 说难听点,垃圾rank#18. 都不用粘人名就知道我是哪一个吧... 因为图片不能太长,所以就不 ...
随机推荐
- selenium-webdriver中的显式等待与隐式等待
在selenium-webdriver中等待的方式简单可以概括为三种: 1 导入time包,调用time.sleep()的方法传入时间,这种方式也叫强制等待,固定死等一个时间 2 隐式等待,直接调用i ...
- ORM查询2
目录 十三式 2式(针对外键查询优化) select_related和prefetch_related prefetch_related 查询返回值类型 不等式查询 关键字查询 时间查询 跨表查询 组 ...
- requests模块(get请求)篇
- HTTP for Humans,更简洁更友好- 继承了urllib的所有特征- 底层使用的是urllib3- 开源地址: https://github.com/requests/requests- ...
- C语言-查找一个元素在数组中的位置
#include<stdio.h> #include <stdlib.h> #include <time.h> int search(int key, int a[ ...
- git操作指令,以及常规git代码操作
安装git后操作指令如下:可以查阅git安装使用操作指南详情git安装使用操作图示详情.note 线上可参考指南:http://www.bootcss.com/p/git-guide/ 所有操作在 ...
- 经验分享:程序员如何快速定位问题(BUG)
让我掉下眼泪的 不止内存泄漏 让我夜夜不眠的 不止你的需求 明天还要改多久 你攥着我的手 让我感到为难的 是善变的需求 发布总是在半夜 回滚是永远的愁 错误(Bug)随时的暴漏 困扰着我心头 作为程序 ...
- VS2017-Linux项目-使用第三方库如何配置
1.虚拟机Ubuntu 16.04,安装第三方库,perftools::tcmalloc. 2.Win10下vs2017创建linux项目. 3.项目>>属性>>VC++ 目录 ...
- 玩转ArduinoJson库 V6版本
1.前言 前面,博主已经讲解了ArduinoJson库的V5版本.为了节省时间以及不讨论重复内容,博主建议读者先去阅读一下 玩转ArduinoJson库 V5版本 .重点了解几个东西: JSO ...
- 浅谈原理--hashCode方法
我们时常会判断一个元素是否相等重复,可以用equals方法. 每增加一个元素,我们就可以通过equals方法判断集合中的每一个元素是否重复,但是如果集合中有10000个元素了,我们每添加一个元素的时候 ...
- StringBuffer类讲解
package Main; import java.util.Scanner; public class Main { public static void main(String[] args) { ...