csps模拟测试50反思
又考崩了,T1一眼秒掉错误思路,然后迅速码完,并码完错误暴力,对拍拍上,以为AC。T2想到了二维莫队,发现是子任务就没去打,一直在想别的,T3最后想到60分打法,没有打完,也没时间暴力,挂掉。T2还有一个读错题的锅,T了一个子任务。
考试一定要合理分配时间,确定自己算法的正确性,想到一个类似的算法要敢于去实现。
T1 施工
单调栈优化dp 改变dp定义是优化dp的重要方式
dp[i]表示第i个位置不变的最优答案。枚举j转移,$O(n^2)$,期望得分53
考虑优化,dp[i]只会由最多一个h比它大的j转移过来,维护单调栈即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 1005
using namespace std;
inline int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<='')x=x*+c-,c=getchar();
return x*f;
}
int dp[N][N],h[N],mn[N][N][];
int main()
{
memset(dp,0x3f,sizeof dp);memset(mn,0x3f,sizeof mn);
int n=read(),c=read(),ans=0x7fffffff;
for(int i=;i<=n;i++)h[i]=read();
for(int i=h[];i<=;i++)dp[][i]=(i-h[])*(i-h[]);
mn[][h[]][]=dp[][h[]]-h[]*c;mn[][][]=dp[][]+*c;
for(int j=h[]+;j<=;j++)
mn[][j][]=min(mn[][j-][],dp[][j]-j*c);
for(int j=;j;j--)
{
mn[][j][]=min(mn[][j+][],dp[][j]+j*c);
}
for(int i=;i<=n;i++)
{
for(int j=h[i];j<=;j++)
dp[i][j]=min(mn[i-][j][]+j*c+(j-h[i])*(j-h[i]),mn[i-][j+][]-j*c+(j-h[i])*(j-h[i]));
mn[i][h[i]][]=dp[i][h[i]]-h[i]*c;mn[i][][]=dp[i][]+*c;
for(int j=h[i]+;j<=;j++)
mn[i][j][]=min(mn[i][j-][],dp[i][j]-j*c);
for(int j=;j;j--)
mn[i][j][]=min(mn[i][j+][],dp[i][j]+j*c);
}
for(int i=h[n];i<=;i++)ans=min(ans,dp[n][i]);
cout<<ans<<endl;
return ;
}
30分代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define N 1000005
using namespace std;
inline int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<='')x=x*+c-,c=getchar();
return x*f;
}
long long f[N],h[N],sum[N][];
int n,C;
inline long long solve(int l,int r,long long ll,long long rr)
{
if(l>r)return (l!=)*(r!=n)*abs(h[l-]-h[r+])*C;
long long a=r-l+,c=sum[r][]-sum[l-][]+C*((l!=)*h[l-]+h[r+]*(r!=n)),b=-(l!=)*C-(r!=n)*C-*(sum[r][]-sum[l-][]);
long long x=-1.0*b/a/+0.5;x=max(ll,x);x=min(rr,x);
return /*cout<<(long long)a*x*x+b*x+c+0.5<<endl,*/(double)a*x*x+b*x+c+0.5;
}
int main()
{
n=read(),C=read();
for(int i=;i<=n;++i)h[i]=read(),sum[i][]=sum[i-][]+h[i]*h[i],sum[i][]=sum[i-][]+h[i];
h[]=h[n+]=0x3f3f3f3f;memset(f,0x3f,sizeof f);
f[]=;
for(int i=;i<=n+;++i)
{
long long mx=;
for(int j=i-;~j;--j)
{
if(h[j]>=mx)f[i]=min(f[i],f[j]+solve(j+,i-,mx,min(h[i],h[j])));
mx=max(mx,h[j]);
if(mx>h[i])break;
}
}
cout<<f[n+]<<endl;
}
53分代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define N 1000005 using namespace std; inline int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<='')x=x*+c-,c=getchar();
return x*f;
}
long long f[N],h[N],sum[N][];
int n,C,st[N],top;
inline long long solve(int l,int r,long long ll,long long rr)
{
if(l>r)return (l!=)*(r!=n)*abs(h[l-]-h[r+])*C;
long long a=r-l+,c=sum[r][]-sum[l-][]+C*((l!=)*h[l-]+h[r+]*(r!=n)),b=-(l!=)*C-(r!=n)*C-*(sum[r][]-sum[l-][]);
long long x=-1.0*b/a/+0.5;x=max(ll,x);x=min(rr,x);
return a*x*x+b*x+c;
}
int main()
{
n=read(),C=read();
for(int i=;i<=n;++i)h[i]=read(),sum[i][]=sum[i-][]+h[i]*h[i],sum[i][]=sum[i-][]+h[i];
h[]=h[n+]=0x3f3f3f3f;memset(f,0x3f,sizeof f);
f[]=;
st[++top]=;
for(int i=;i<=n+;++i)
{
long long mx=;
while(top&&h[st[top]]<=h[i])f[i]=min(f[i],f[st[top]]+solve(st[top]+,i-,mx,h[st[top]])),mx=h[st[top--]];
if(top)f[i]=min(f[i],f[st[top]]+solve(st[top]+,i-,mx,h[i]));
st[++top]=i;
}
cout<<f[n+]<<endl;
}
AC代码
T2 蔬菜
二维莫队(留一个坑,以后一定要学一学回滚莫队,树上莫队)板子题
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
map<int,int>mp;
int t[],bl[],ans,q,s[][],b[],tot;
inline int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<='')x=x*+c-,c=getchar();
return x*f;
}
struct query{
int lx,ly,rx,ry,id,ans;
friend bool operator < (const query a,const query b)
{
if(bl[a.lx]!=bl[b.lx])return bl[a.lx]<bl[b.lx];
if(bl[a.ly]!=bl[b.ly])return bl[a.ly]<bl[b.ly];
if(bl[a.rx]!=bl[b.rx])return bl[a.rx]<bl[b.rx];
return a.ry<b.ry;
}
inline void init(int x){lx=read(),ly=read(),rx=read(),ry=read(),id=x;}
}Q[];
inline void add(int x,int y)
{
ans-=t[s[x][y]]*t[s[x][y]];
t[s[x][y]]++;
ans+=t[s[x][y]]*t[s[x][y]];
return ;
}
inline void del(int x,int y)
{
ans-=t[s[x][y]]*t[s[x][y]];
t[s[x][y]]--;
ans+=t[s[x][y]]*t[s[x][y]];
}
inline void Add(int lx,int ly,int rx,int ry)
{
for(register int i=lx;i<=rx;i++)
for(register int j=ly;j<=ry;j++)
add(i,j);
}
inline void Del(int lx,int ly,int rx,int ry)
{
for(register int i=lx;i<=rx;i++)
for(register int j=ly;j<=ry;j++)
del(i,j);
}
void work()
{
sort(Q+,Q+q+);
int lx=,ly=,rx=,ry=;
for(int i=;i<=q;i++)
{
while(lx>Q[i].lx)lx--,Add(lx,ly,lx,ry);
while(rx<Q[i].rx)rx++,Add(rx,ly,rx,ry);
while(ly>Q[i].ly)ly--,Add(lx,ly,rx,ly);
while(ry<Q[i].ry)ry++,Add(lx,ry,rx,ry); while(lx<Q[i].lx)Del(lx,ly,lx,ry),lx++;
while(rx>Q[i].rx)Del(rx,ly,rx,ry),rx--;
while(ly<Q[i].ly)Del(lx,ly,rx,ly),ly++;
while(ry>Q[i].ry)Del(lx,ry,rx,ry),ry--;
Q[i].ans=ans;
}
sort(Q+,Q+q+,[](query a,query b){
return a.id<b.id;
});
}
int main()
{
int r=read(),c=read();q=read();const int t=;
for(int i=;i<=;i++)bl[i]=(i-)/t+;
for(int i=;i<=r;i++)
for(int j=;j<=c;j++)
s[i][j]=read(),b[++tot]=s[i][j];
sort(b+,b+tot+);tot=unique(b+,b+tot+)-b-;
for(int i=;i<=tot;i++)mp[b[i]]=i;
for(int i=;i<=r;i++)
for(int j=;j<=c;j++)
s[i][j]=mp[s[i][j]];
for(int i=;i<=q;i++)Q[i].init(i);
work();
for(int i=;i<=q;i++)printf("%d\n",Q[i].ans);
return ;
}
T3 联盟
枚举断边,连边的时候出于最优的策略,会连接两条直径的中点,预处理即可。
直径的性质:不一定唯一,直径的中点是距离所有点距离最大值最小的点。
#include<cstdio>
#include<iostream>
#define N 300005
using namespace std;
int f[][N][],maxd,a,b,nxt[N<<],to[N<<],head[N],cnt=,pre[N],in[N<<],ff[N];
char v[N<<],cut[N<<];
int q[N],tot,ed[N],st[N];
inline void Add(int u,int v)
{
to[++cnt]=v;nxt[cnt]=head[u];
head[u]=cnt;
}
inline int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<='')x=x*+c-,c=getchar();
return x*f;
}
void dp(int x,int fa,int opt)
{
int mx=,sec=;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa)continue;
dp(y,x,opt);
if(f[opt][y][]+>mx)sec=mx,mx=f[opt][y][]+;
else if(f[opt][y][]+>sec)sec=f[opt][y][]+;
f[opt][x][]=max(f[opt][x][],f[opt][y][]);
}
f[opt][x][]=mx;
f[opt][x][]=max(mx+sec,f[opt][x][]);
}
void dfs1(int x,int fa,int dis)
{
if(dis>=maxd)a=x,maxd=dis;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa||cut[i])continue;
dfs1(y,x,dis+);
}
}
void dfs2(int x,int fa,int dis)
{
if(dis>=maxd)b=x,maxd=dis;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa||cut[i])continue;
pre[y]=i;ff[y]=x;
v[i]=;
dfs2(y,x,dis+);
}
}
int main()
{
int n=read(),ans=0x7f7f7f7f,len=;
for(int i=;i<n;i++)
st[i]=read(),ed[i]=read(),
Add(st[i],ed[i]),Add(ed[i],st[i]);
dfs1(,,);maxd=;dfs2(a,,);
for(int i=b;i;i=ff[i])in[pre[i]]=;len=maxd;
dp(a,,),dp(b,,);
for(int i=;i<n;i++)
{
if(v[i<<]&&in[i<<])
{
int l1=f[][ed[i]][],l2=f[][st[i]][],tmp=;
tmp=max(l1,max(l2,(l1+)/++(l2+)/));
if(tmp<ans)ans=tmp,q[tot=]=i;
else if(tmp==ans)q[++tot]=i;
}
else if(v[i<<|]&&in[i<<|])
{
int l1=f[][ed[i]][],l2=f[][st[i]][],tmp=;
tmp=max(l1,max(l2,(l1+)/++(l2+)/));
if(tmp<ans)ans=tmp,q[tot=]=i;
else if(tmp==ans)q[++tot]=i;
}
else if(v[i<<])
{
int tmp=len;
if(tmp<ans)ans=tmp,q[tot=]=i;
else if(tmp==ans)q[++tot]=i;
}
else if(v[i<<|])
{
int tmp=len;
if(tmp<ans)ans=tmp,q[tot=]=i;
else if(tmp==ans)q[++tot]=i;
}
}
printf("%d\n%d ",ans,tot);
for(int i=;i<=tot;i++)printf("%d ",q[i]);
puts("");int s,t;
cout<<st[q[]]<<' '<<ed[q[]]<<' ';
cut[q[]<<]=cut[q[]<<|]=;maxd=;
dfs1(st[q[]],,);maxd=,dfs2(a,,);len=maxd,maxd=;
for(int i=b,cnt=;i;i=ff[i],cnt++)
if(cnt==len/){cout<<i<<' ';break;}maxd=;
dfs1(ed[q[]],,);maxd=,dfs2(a,,);len=maxd,maxd=;
for(int i=b,cnt=;i;i=ff[i],cnt++)
if(cnt==len/){cout<<i<<' ';break;}
}
附上带修主席树代码
#include<cstdio>
#define N 100050
using namespace std;
const int inf=1e9;
int rt[N],a[N],n;
struct Segtree{
int s[N<<],ls[N<<],rs[N<<],tot,tmp[][],cnt[];
inline void up(int k){s[k]=s[ls[k]]+s[rs[k]];return ;}
void change(int &k,int l,int r,int pos,int val)
{
if(!k)k=++tot;
if(l==r){s[k]+=val;return ;}
int mid=l+r>>;
if(pos<=mid) change(ls[k],l,mid,pos,val);
else change(rs[k],mid+,r,pos,val);
up(k);
}
int query(int k,int l,int r,int ll,int rr)
{
if(l==ll&&r==rr)return s[k];
int mid=l+r>>;
if(ll<=mid)return query(ls[k],l,mid,ll,rr);
else return query(rs[k],mid+,r,ll,rr);
}
int __query(int l,int r,int k)
{
if(l==r)return l;
int mid=l+r>>,nowsum=;
for(int i=;i<=cnt[];i++) nowsum-=s[ls[tmp[][i]]];
for(int i=;i<=cnt[];i++) nowsum+=s[ls[tmp[][i]]];
if(nowsum>=k)
{
for(int i=;i<=cnt[];i++) tmp[][i]=ls[tmp[][i]];
for(int i=;i<=cnt[];i++) tmp[][i]=ls[tmp[][i]];
return __query(l,mid,k);
}
else
{
for(int i=;i<=cnt[];i++) tmp[][i]=rs[tmp[][i]];
for(int i=;i<=cnt[];i++) tmp[][i]=rs[tmp[][i]];
return __query(mid+,r,k-nowsum);
}
}
inline int _query(int l,int r,int k)
{
cnt[]=cnt[]=;
for(int i=l-;i;i-=i&-i) tmp[][++cnt[]]=rt[i];
for(int i=r;i;i-=i&-i) tmp[][++cnt[]]=rt[i];
return __query(-inf,inf,k);
}
inline void _change(int pos,int val,int opt)
{
int fr=a[pos];
for(;pos<=n;pos+=pos&-pos)
{
if(opt) change(rt[pos],-inf,inf,fr,-);
change(rt[pos],-inf,inf,val,);
}
return ;
}
}T;
int main()
{
int m;scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
T._change(i,a[i],);
}
while(m--)
{
char opt[];
scanf("%s",opt);
if(opt[]=='C')
{
int x,v;
scanf("%d%d",&x,&v);
T._change(x,v,);
a[x]=v;
}
else
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
printf("%d\n",T._query(l,r,x));
}
}
return ;
}
csps模拟测试50反思的更多相关文章
- [CSP-S模拟测试50]反思+题解
??大部分人都觉得T3是道不可做题去刚T1T2了,于是我就侥幸苟到了前面? 这场考试比较成功的就是快速水掉了T1T2的部分分,1h拿到88分起码为之后硬肝T3上了保险(赛后发现就算T3爆零也能rank ...
- 2019.10.30 csp-s模拟测试94 反思总结
头一次做图巨的模拟题OWO 自从上一次听图巨讲课然后骗了小礼物以后一直对图巨印象挺好的233 T1: 对于XY取对数=Y*log(x) 对于Y!取对数=log(1*2*3*...*Y)=log1+lo ...
- 2019.9.28 csp-s模拟测试54 反思总结
咕咕咕的冲动如此强烈x T1x: 看完题目想了想,感觉把gcd不为1的强行放在一组,看作一个连通块,最后考虑连通块之间的组合方式就可以了. 然后维护这个连通块可以写并查集可以连边跑dfs怎么着都行… ...
- csp-s模拟测试50(9.22)「施工(单调栈优化DP)」·「蔬菜(二维莫队???)」·「联盟(树上直径)」
改了两天,终于将T1,T3毒瘤题改完了... T1 施工(单调栈优化DP) 考场上只想到了n*hmaxn*hmaxn的DP,用线段树优化一下变成n*hmaxn*log但显然不是正解 正解是很**的单调 ...
- csps模拟测试92反思
连着挂了三天T1了. 89: SPFA$vst$数组没清空 90:调试的时候多删了一句代码 91:没开$long long$ 我真是废物. 希望以后不要犯SB错误了
- [CSP-S模拟测试48]反思+题解
状态很垃圾的一场考试.感觉“这么多分就够了”的心态很是在给自己拖后腿. 打开题面,第一页赫然写着:$Claris' Contest$. 吓得我差点手一抖关掉.不过后来想想似乎强到变态的人出的题都不是很 ...
- [CSP-S模拟测试47]反思+题解
打开题面,T3似乎被换过了.(那我就更有理由直接弃掉了) T1是我最害怕的乱搞题,赶紧扔了看T2.发现是个sb板子?雨天的尾巴弱化版? 然而线段树合并早忘干净了(最近几道可以线段树合并的题都是用别的方 ...
- 2019.10.29 csp-s模拟测试93 反思总结
T1: 求出前缀和,三维偏序O(nlog2n)CDQ 二维其实就可以 #include<iostream> #include<cstdio> #include<cstri ...
- 2019.10.29 csp-s模拟测试92 反思总结
今天快乐的墨雨笙因为什么而几乎爆零了呢? 顾此失彼+不会对拍+无脑的复杂度 今天高兴的墨雨笙又因为什么调了一个下午呢? 不明题意+不想范围+板子低级错误 R.I.P. T1: //唉 //害怕TLE, ...
随机推荐
- 安装vant2.2.7版本报错These dependencies were not found: vant/es/goods-action-big-btn in ./src/config/vant.config.js......
一.问题 前天,在使用vant的checkbox复选框的时候,注意到新增加一个全选功能,通过 ref 可以获取到 CheckboxGroup 实例并调用实例方法.于是我就想用这个,但是按照上面的示例写 ...
- 【JavaScript】 直接下载保存文件
//直接下载保存文件 function Download(filePath) { // 如果中间IFRAME不存在,则添加 if (!document.getElementById("_SA ...
- 【线性表基础】顺序表和单链表的插入、删除等基本操作【Java版】
本文表述了线性表及其基本操作的代码[Java实现] 参考书籍 :<数据结构 --Java语言描述>/刘小晶 ,杜选主编 线性表需要的基本功能有:动态地增长或收缩:对线性表的任何数据元素进行 ...
- docker镜像命令使用
创建docker容器时使用的docker镜像如果在本地中不存在,docker就会自动从docker镜像仓库中下载,默认的docker镜像仓库是Docker Hub公共镜像源 使用docker sear ...
- Paid Roads POJ - 3411
A network of m roads connects N cities (numbered from 1 to N). There may be more than one road conne ...
- COGS 2096. 不平凡的许愿树
[题目描述] noip要到了,大家来到许愿树前.这个许愿树不仅仅是许愿树,还有未卜先知的功能.众OIer问许愿树:“不平凡的许愿树,CCF告诉我们noip中会有两道题目从Openjudge上选择,你能 ...
- 本人亲测-SSM整合后的基础包(供新手学习使用,可在本基础上进行二次开发)
本案例是在eclipse上进行开发的,解压后直接添加到eclipse即可.还需要自己配置maven环境.链接:https://pan.baidu.com/s/1siuvhCJASuZG_jqY5utP ...
- .net core 3.0 WPF中使用FolderBrowserDialog
前言 随着.net core 3.0 的发布,WPF 也可以在 core 平台上使用了.当前的 WPF 不支持跨平台,仅能够在 Windows 平台上使用.如果想体验 WPF 跨平台开发,可以访问开源 ...
- session与cookie,django中间件
0819自我总结 一.session与cookie 1.django设置session request.session['name'] = username request.session['age' ...
- 那些你不知道的HTML知识,快来学习一下吧
前言 HTML作为前端三大基础知识点之一,是每一个前端开发人员都要掌握的部分.今天这篇文章我们来看看一些平时不太会注意,却在面试时可能会问到的题目,来看看你都会吗? 如何使用div模拟实现textar ...