【学习笔记】模拟赛题解

混乱邪恶

构造题的第一步总是最难想的。

考虑 n n n是偶数的情况,否则添加一个 0 0 0

首先把数从大到小排序,然后相邻的两个数配对,记其差为 s i s_i si

注意到 n ∈ [ 2 3 m , m ] n\in [\frac{2}{3}m,m] n[32m,m],因此 ∑ s i ≤ m − n 2 < n \sum s_i\le m-\frac{n}{2}<n sim2n<n

这就很有意思了。也就是说至少存在 n 2 \frac{n}{2} 2n 1 1 1,同时注意到 s i s_i si最大值不超过 m − n m-n mn

显然 n 2 ≥ m − n \frac{n}{2}\ge m-n 2nmn。那么可以设计如下算法:

s i s_i si从大到小排序,如果当前 s u m < 0 sum<0 sum<0,那么加上 s i s_i si,如果 s u m ≥ 0 sum\ge 0 sum0那么减去 s i s_i si

当然本题还有另一种构造方案。具体是让最大值减最小值,这样每次迭代完 ∑ s i \sum s_i si不超过数的个数的两倍。最后规约到 2 2 2个数的情况即可。

代码:

我信仰什么,我便实现哪种方法。

#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back using namespace std; int n,m,a[1000005],id[1000005],res[1000005]; ll sum; vector<int>v2; struct node{ int x,y,d; bool operator <(const node &a)const { return d>a.d; } }; vector<node> v3; int main() { ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); memset(res,-1,sizeof res); cin>>n>>m; for(int i=1;i<=n;i++) { int x;cin>>x,id[x]=i,a[x]=1; } for(int i=m;i>=1;i--) { if(a[i]) { v2.pb(i); } } for(int i=0;i+1<v2.size();i+=2) { v3.pb({v2[i],v2[i+1],v2[i]-v2[i+1]}); } if(v2.size()&1) { v3.pb({v2.back(),0,v2.back()}); }sort(v3.begin(),v3.end()); for(auto &x:v3) { if(sum<0) sum+=x.d,res[id[x.x]]=1; else sum-=x.d,res[id[x.y]]=1; } if(sum==0) { cout<<"NP-Hard solved"<<endl; for(int i=1;i<=n;i++) cout<<res[i]<<' '; } else { cout<<"Chaotic evil"; } }

鸽子

sb数据结构题

类比 z k w zkw zkw线段树,可以把 l → r l\to r lr的路径提出来。

然后大力重链剖分。具体是每条重链维护两棵线段树,分别维护与这条链相邻的左子树和右子树。(若一个点的左子树不在链上则这个点维护左子树,否则这个点维护右子树)

跳轻链的过程是单点修改+单点查询,直接用数组维护即可。

注意到我维护的是两个不同的方向,所以把两个部分的答案加起来即可。

复杂度 O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)

代码:

#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back using namespace std; int n,m,rt,num,rk[400005]; int ls[400005],rs[400005]; int dfn[400005],siz[400005],son[400005],num2; int vs[400005],tp[400005],dep[400005],fa[400005]; ll s[1600020]; struct sgt{ ll t[1600020],tag[1600020],siz[1600020]; void add(int p,ll x) { t[p]+=siz[p]*x,tag[p]+=x; } void pushdown(int p) { if(tag[p]) add(p<<1,tag[p]),add(p<<1|1,tag[p]),tag[p]=0; } void ins(int p,int l,int r,int x,int y) { siz[p]+=y;if(l==r) return; int mid=l+r>>1;x<=mid?ins(p<<1,l,mid,x,y):ins(p<<1|1,mid+1,r,x,y); } void upd(int p,int l,int r,int ql,int qr,ll x) { if(ql>qr) return; if(ql<=l&&r<=qr) { add(p,x); return; }int mid=l+r>>1;pushdown(p); if(ql<=mid) upd(p<<1,l,mid,ql,qr,x); if(mid<qr) upd(p<<1|1,mid+1,r,ql,qr,x); t[p]=t[p<<1]+t[p<<1|1]; } ll qry(int p,int l,int r,int ql,int qr) { if(ql>qr) return 0; if(ql<=l&&r<=qr) return t[p]; int mid=l+r>>1;pushdown(p); if(qr<=mid) return qry(p<<1,l,mid,ql,qr); if(mid<ql) return qry(p<<1|1,mid+1,r,ql,qr); return qry(p<<1,l,mid,ql,qr)+qry(p<<1|1,mid+1,r,ql,qr); } }T[2]; void upd(int x,ll d) { s[x]+=d*siz[son[x]]; } void dfs(int u,int topf) { fa[u]=topf,dep[u]=dep[topf]+1; if(!ls[u]) { siz[u]=1,rk[++num]=u; return; }dfs(ls[u],u),dfs(rs[u],u);siz[u]+=siz[ls[u]]+siz[rs[u]]; son[u]=(siz[ls[u]]>siz[rs[u]])?ls[u]:rs[u]; } void dfs2(int u,int topf) { dfn[u]=++num2,tp[u]=topf; if(!ls[u]) return; if(ls[u]==son[u]) dfs2(ls[u],topf),dfs2(rs[u],rs[u]),T[1].ins(1,1,n,dfn[u],siz[rs[u]]); else dfs2(rs[u],topf),dfs2(ls[u],ls[u]),T[0].ins(1,1,n,dfn[u],siz[ls[u]]); } void modify(int x,int y,ll d) { int fx=tp[x],fy=tp[y]; while(fx!=fy) { if(dep[fx]>dep[fy]) { T[1].upd(1,1,n,dfn[fx],dfn[x]-1,d),x=fa[fx]; if(tp[x]!=tp[y]&&rs[x]==son[x]) { upd(x,d); } } else { T[0].upd(1,1,n,dfn[fy],dfn[y]-1,d),y=fa[fy]; if(tp[x]!=tp[y]&&ls[y]==son[y]) { upd(y,d); } }fx=tp[x],fy=tp[y]; } if(dep[x]>dep[y]) { T[1].upd(1,1,n,dfn[y]+1,dfn[x]-1,d); } else { T[0].upd(1,1,n,dfn[x]+1,dfn[y]-1,d); } } ll qry(int x,int y) { int fx=tp[x],fy=tp[y];ll res=0; while(fx!=fy) { if(dep[fx]>dep[fy]) { res+=T[1].qry(1,1,n,dfn[fx],dfn[x]-1),x=fa[fx]; if(tp[x]!=tp[y]&&rs[x]==son[x]) { res+=s[x]; } } else { res+=T[0].qry(1,1,n,dfn[fy],dfn[y]-1),y=fa[fy]; if(tp[x]!=tp[y]&&ls[y]==son[y]) { res+=s[y]; } }fx=tp[x],fy=tp[y]; } if(dep[x]>dep[y]) { res+=T[1].qry(1,1,n,dfn[y]+ 1,dfn[x]-1); } else { res+=T[0].qry(1,1,n,dfn[x]+1,dfn[y]-1); } return res; } int main() { ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>m;memset(vs,-1,sizeof vs); for(int i=1;i<n;i++) { cin>>ls[n+i]>>rs[n+i]; vs[ls[n+i]]=0,vs[rs[n+i]]=1; }for(int i=n+1;i<2*n;i++) { if(vs[i]==-1) rt=i; }n=2*n-1;int x=++n,y=++n,z=++n,w=++n;ls[x]=rt,rs[x]=y,ls[z]=w,rs[z]=x;dfs(z,0),dfs2(z,z); for(int i=1;i<=m;i++) { int op,l,r,d; cin>>op>>l>>r; if(op==1) { cin>>d; modify(rk[l],rk[r+2],d); } else { cout<<qry(rk[l],rk[r+2])<<endl; } } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530098.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示