日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 1539F Strange Array(线段树区间合并)

發布時間:2024/4/11 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1539F Strange Array(线段树区间合并) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個長度為 nnn 的序列,規定位置 iii 的貢獻是:設 x=a[i]x=a[i]x=a[i],選擇一個包含 iii 的區間 [l,r][l,r][l,r],將其中的數排序后,使得中位數和 xxx 之間的距離的最大值。題目要求輸出 nnn 個位置的答案

題目分析:

xxx 為中位數,將大于 xxx 的位置視為 111,小于 xxx 的位置視為 ?1-1?1 ,然后求最長連續子段和,是解決中位數問題經典模型。

對于本題而言,假設只需要詢問一個位置的話,可以從該位置向左向右擴展,找連續子段和最大、最小的位置。換言之我們需要查找從某個位置向左向右的最大、最小連續子段和

那么問題的瓶頸就變成了,對于不同的位置,如何快速修改并維護貢獻呢

其實不難看出,我們并不需要在計算完 i?1i-1i?1 的答案后立馬去計算位置 iii 的答案

所以呢?我們可以對權值進行排序,這樣維護整個數列就變得很簡單了

而計算上文中提到的“從某個位置向左向右的最大、最小連續子段和”,正是前幾日藍橋杯國賽的那個括號序列原題。。線段樹區間合并一下就可以了,查詢的時候可以直接返回結構體,也可以返回數值,無非是 O(nlogn)O(nlogn)O(nlogn)O(nlog2n)O(nlog^2n)O(nlog2n) 的區別罷了

代碼:

// Problem: F. Strange Array // Contest: Codeforces - Codeforces Round #727 (Div. 2) // URL: https://codeforces.com/contest/1539/problem/F // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=2e5+100; int n,ans[N]; vector<int>node[N]; struct Node {int l,r,lmax,rmax,lmin,rmin,sum; }tree[N<<2]; Node zero={0,0,0,0,0,0,0}; void change(int k,int x) {tree[k].lmax=tree[k].rmax=tree[k].lmin=tree[k].rmin=tree[k].sum=x; } Node merge(Node a,Node b) {Node ans;ans.l=a.l,ans.r=b.r;ans.sum=a.sum+b.sum;ans.lmax=max(a.lmax,a.sum+b.lmax);ans.lmin=min(a.lmin,a.sum+b.lmin);ans.rmin=min(b.rmin,b.sum+a.rmin);ans.rmax=max(b.rmax,b.sum+a.rmax);return ans; } void build(int k,int l,int r) {tree[k].l=l,tree[k].r=r;if(l==r) {change(k,1);return;}int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);tree[k]=merge(tree[k<<1],tree[k<<1|1]); } void update(int k,int pos) {if(tree[k].l==tree[k].r) {change(k,-1);return;}int mid=(tree[k].l+tree[k].r)>>1;if(pos<=mid) {update(k<<1,pos);} else {update(k<<1|1,pos);}tree[k]=merge(tree[k<<1],tree[k<<1|1]); } Node query(int k,int l,int r) {if(l>r) {return zero;}if(tree[k].l>r||tree[k].r<l) {return zero;} if(tree[k].l>=l&&tree[k].r<=r) {return tree[k];}return merge(query(k<<1,l,r),query(k<<1|1,l,r)); } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);read(n);build(1,1,n);for(int i=1;i<=n;i++) {int x;read(x);node[x].push_back(i);}for(int i=1;i<=n;i++) {for(auto p:node[i]) {update(1,p);}for(auto p:node[i]) {Node l=query(1,1,p-1),r=query(1,p+1,n);int lmin=min(l.rmin,0);int rmin=min(r.lmin,0);int lmax=max(l.rmax,0);int rmax=max(r.rmin,0);ans[p]=max({ans[p],(lmax+rmax+1)/2,(-lmin-rmin)/2});}}build(1,1,n);for(int i=n;i>=1;i--) {for(auto p:node[i]) {update(1,p);}for(auto p:node[i]) {Node l=query(1,1,p-1),r=query(1,p+1,n);int lmin=min(l.rmin,0);int rmin=min(r.lmin,0);int lmax=max(l.rmax,0);int rmax=max(r.rmin,0);ans[p]=max({ans[p],(lmax+rmax)/2,(-lmin-rmin+1)/2});}}for(int i=1;i<=n;i++) {printf("%d ",ans[i]);}return 0; } 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的CodeForces - 1539F Strange Array(线段树区间合并)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。