预祝2025省选嗨翻天
预祝2025省选嗨翻天
A. 单峰序列
-
部分分
:枚举每个数在单峰序列的左边还是右边,求次数做法同 luogu P3531 [POI 2012] LIT-Letters 。
点击查看代码
int a[500010],b[500010],c[500010],ans[500010],id; vector<int>l,r; struct BIT { int c[500010]; int lowbit(int x) { return (x&(-x)); } void add(int n,int x,int val) { for(int i=x;i<=n;i+=lowbit(i)) c[i]+=val; } int getsum(int x) { int ans=0; for(int i=x;i>=1;i-=lowbit(i)) ans+=c[i]; return ans; } }T; void dfs(int pos,int n) { if(pos==n+1) { b[0]=0; for(int i=0;i<l.size();i++) { b[0]++; b[b[0]]=l[i]; } sort(b+1,b+1+b[0]); b[0]++; b[b[0]]=a[id]; int tmp=b[0]+1; for(int i=0;i<r.size();i++) { b[0]++; b[b[0]]=r[i]; } sort(b+tmp,b+1+b[0],greater<int>()); for(int i=1;i<=n;i++) c[b[i]]=i; for(int i=1;i<=n;i++) tmp=0; for(int i=n;i>=1;i--) { tmp+=T.getsum(c[a[i]]-1); T.add(n,c[a[i]],1); } ans[n]=min(ans[n],tmp); for(int i=1;i<=n;i++) T.add(n,c[a[i]],-1); } else { if(pos==id) dfs(pos+1,n); else { l.push_back(a[pos]); dfs(pos+1,n); l.pop_back(); r.push_back(a[pos]); dfs(pos+1,n); r.pop_back(); } } } int main() { #define Isaac #ifdef Isaac freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); #endif int n,t,i; cin>>n>>t; memset(ans,0x3f,sizeof(ans)); for(i=1;i<=n;i++) { cin>>a[i]; if(a[i]>a[id]) id=i; dfs(1,i); } if(t==1) for(i=1;i<=n;i++) cout<<ans[i]<<endl; else cout<<ans[n]<<endl; return 0; }
-
正解
- 考虑
在最终单峰序列中位于 前还是 后,两者产生的逆序对/交换次数分别为 ,不妨设两个值分别为 。贪心地取 作为其贡献即可。 - 观察到
随着 单调不降,考虑二分找到其分界点 使得 以前 , 以后 。 - 动态维护
的变化,此时是一个矩阵加、单点查询的形式,扫描线即可。
点击查看代码
ll a[500010],pos[500010],sum[500010]; vector<ll>c[500010]; struct BIT { ll c[500010]; ll lowbit(ll x) { return (x&(-x)); } void clear() { memset(c,0,sizeof(c)); } void add(ll n,ll x,ll val) { for(ll i=x;i<=n;i+=lowbit(i)) c[i]+=val; } void update(ll n,ll l,ll r,ll val) { add(n,l,val); add(n,r+1,-val); } ll getsum(ll x) { ll ans=0; for(ll i=x;i>=1;i-=lowbit(i)) ans+=c[i]; return ans; } }B[2]; int main() { #define Isaac #ifdef Isaac freopen("seq.in","r",stdin); freopen("seq.out","w",stdout); #endif ll n,t,ans,l,r,mid,i,j; scanf("%lld%lld",&n,&t); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); pos[a[i]]=i; B[0].add(n,a[i],1); sum[i]=i-B[0].getsum(a[i]); } B[0].clear(); for(i=n;i>=1;i--) { l=pos[i]; r=n; ans=0; while(l<=r) { mid=(l+r)/2; if(B[0].getsum(mid)-B[0].getsum(pos[i])<=sum[pos[i]]) { ans=mid; l=mid+1; } else r=mid-1; } c[ans+1].push_back(a[pos[i]]); B[0].add(n,pos[i],1); } ans=0; for(i=1;i<=n;i++) { if(a[i]+1<=n) B[1].update(n,a[i]+1,n,1); for(j=0;j<c[i].size();j++) B[1].update(n,c[i][j],n,-1); ans+=B[1].getsum(a[i]); if(i==n||t==1) printf("%lld\n",ans); } return 0; }
- 考虑
B. 划分线段
-
部分分
:输出 。
-
正解
C. 红蓝树
-
部分分
:模拟。
点击查看代码
int a[600010]; stack<int>s; int main() { #define Isaac #ifdef Isaac freopen("rbtree.in","r",stdin); freopen("rbtree.out","w",stdout); #endif int n,m,pd,l,r,ans=0,col,i,j; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]--; } for(j=1;j<=m;j++) { scanf("%d%d%d",&pd,&l,&r); if(pd==1) for(i=l;i<=r;i++) a[i]^=1; else { ans=col=0; while(s.empty()==0) s.pop(); for(i=l;i<=r;i++) { if(a[i]<=1) { ans+=(a[i]||col); s.push((a[i]||col)); col=0; } else if(s.empty()==0) { col|=s.top(); s.pop(); } } printf("%d\n",ans); } } return 0; }
-
正解
总结
- 罚坐。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18739449,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具