CF1710B&如何理解一阶/二阶差分后最值取点数量只有 O(n)

如何理解一阶/二阶差分后最值取点数量只有 O(n)

一阶的显然。

考虑一系列操作都可以化成 O(n) 个单点二阶差分加。

考虑对于 2 个不为 0 的二阶差分,i,j,那么 (i,j) 这个区间是不是一阶差分都一样,那么最后的前缀和是不是 i+1 叠的值最少,j1 叠的最多,所以最值一定在 i,i+1,j1,j 四个位置出现。然后加可能负数,所以对于每个二阶差分单点加的点只要顺带记录它 +1 即可。

https://codeforces.com/contest/1710/problem/B

例题捏!

考虑转化为 2 个等差数列,那么显然二阶差分。至于怎么加这个就需要现场手推了。然后就记录下 +1,最后判断下就好了。

#include <bits/stdc++.h> #define int long long #define pb push_back using namespace std; int rd() { int sum=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch<='9'&&ch>='0') { sum=sum*10+ch-'0'; ch=getchar(); } return sum*f; } const int N=(int)(2e6+5),inf=(int)(2e18); struct ques { int x,p; }a[N]; pair<int,int>d[N],A[N]; int n,m,mx1[N],mx2[N]; map<int,int>mp,mp2; void solve() { n=rd(); m=rd(); mp.clear(); mp2.clear(); // add2(1,5,0); for(int i=1;i<=n;i++) { int x=rd(),p=rd(); a[i].x=x; a[i].p=p; mp[x]+=0; mp[x-1]+=0; mp[x+p-1]+=0; mp[x+p]+=0; mp[x-p+1]++; mp[x+1]+=-1-p; mp[x+2]+=p; --p; if(p>=0) { mp[x+1]+=p; mp[x+2]+=-1-p; mp[x+p+2]+=1; } } int tot=0; for(auto it=mp.begin();it!=mp.end();++it) { // cout<<(*it).first<<" "<<(*it).second<<'\n'; ++tot; mp2[(*it).first]=tot; d[tot]=make_pair((*it).first,(*it).second); } sort(d+1,d+1+tot); // cout<<'\n'; // d[0]=make_pair(0,0); for(int i=2;i<=tot;i++) d[i].second+=d[i-1].second; // for(int i=1;i<=tot;i++) { //// d[i].second+=d[i-1].second*(d[i].first-d[i-1].first); // cout<<d[i].first<<" "<<d[i].second<<'\n'; // } // cout<<'\n'; A[1]=d[1]; for(int i=2;i<=tot;i++) { A[i].first=d[i].first; if(d[i].first==d[i-1].first+1) A[i].second=d[i].second+A[i-1].second; else A[i].second=d[i].second+A[i-1].second+d[i-1].second*(d[i].first-d[i-1].first-1); // cout<<d[i].first<<" "<<A[i].second<<'\n'; } // cout<<'\n'; // for(int i=1;i<=tot;i++) cout<<A[i].first<<" "<<A[i].second<<'\n'; mx1[0]=mx2[tot+1]=-inf; for(int i=1;i<=tot;i++) { if(A[i].second>m) mx1[i]=max(mx1[i-1],A[i].second-A[i].first); else mx1[i]=mx1[i-1]; } for(int i=tot;i>=1;i--) { if(A[i].second>m) mx2[i]=max(mx2[i+1],A[i].first+A[i].second); else mx2[i]=mx2[i+1]; } // for(int i=1;i<=n;i++) { // bool fl=1; // for(int j=1;j<=tot;j++) { // int qwq=max(0ll,a[i].p-abs(a[i].x-A[j].first)); // if(A[j].second-qwq>m) { // fl=0; break ; // } // } // if(fl) printf("1"); // else printf("0"); // } // int res=0; for(int i=1;i<=n;i++) { int id=mp2[a[i].x]; // cout<<id<<" "<<mx1[id]<<" "<<mx2[id]<<'\n'; if(mx1[id]<=m+a[i].p-a[i].x&&mx2[id]<=m+a[i].p+a[i].x) { printf("1"); } else printf("0"); } printf("\n"); for(int i=0;i<=tot;i++) { mx1[i]=mx2[i]=-inf; A[i]=d[i]=make_pair(0,0); } } signed main() { int T=rd(); while(T--) solve(); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16534112.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示