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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Codeforces Round #727 (Div. 2) F. Strange Array 线段树 + 区间合并 + 排序优化

發布時間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces Round #727 (Div. 2) F. Strange Array 线段树 + 区间合并 + 排序优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

文章目錄

  • 題意:
  • 思路:

題意:

給你一個長度為nnn的數組,對每個位置iii求一個最大價值,價值計算方式如下:選擇一個包含iii[l,r][l,r][l,r],讓后將其拿出來排序,之后價值就是當前位置的值aia_iai?在排序后的位置到中位數的位置的距離,如果有相同的值位置可以任意安排,中位數的位置定義為:如果長度為奇數位置就是l+r2\frac{l+r}{2}2l+r?,否則l+r+12\frac{l+r+1}{2}2l+r+1?。

思路:

對于每個位置,我們可以想到分兩種情況貪心,一種是讓≤ai\le a_iai?的盡可能多,另一種是讓≥ai\ge a_iai?的盡可能多,我們只討論第一種,就是讓≤ai\le a_iai?的盡可能多。
在確定aia_iai?之后就有一個比較套路的做法了,我們可以將>ai>a_i>ai?的都設為?1-1?1≤ai\le a_iai?的都設為111,這樣我們就可以從[i+1,n][i+1,n][i+1,n]找一個值最大的前綴,從[1,i?1][1,i-1][1,i?1]找一個值最大的后綴,讓后二者結合起來為sumsumsum,答案就是sum2\frac{sum}{2}2sum??,F在問題就轉換成如何快速求最長前綴和最長后綴了。
這也是一個經典問題,將其放在線段樹上,維護個lmax,rmax,sumlmax,rmax,sumlmax,rmax,sum即可。
目前我們這個問題已經解決了一半了,現在是如何將≤ai\le a_iai?的都賦為111>ai>a_i>ai?的賦為?1-1?1呢?我們不能每次都暴力修改,考慮將每個值對應的ididid都放在一個桶里,初始的時候讓每個位置都為?1-1?1,讓后從[1,n][1,n][1,n]遍歷這個桶,每次將當前桶內的ididid位置都變成111即可,這樣放在桶里就可以很好的解決這個問題了。
對于另一種情況,他的答案應該為sum+12\frac{sum+1}{2}2sum+1?,這個跟中位數的位置有關系,偶數的話中位數是靠近右邊的內個數,所以如果sumsumsum表示的是≥ai\ge a_iai?的個數的話,那么aia_iai?在最左邊,所以要上取整。

// 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("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #include<random> #include<cassert> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid ((tr[u].l+tr[u].r)>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=200010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n,m; int ans[N]; struct node {int val,id;bool operator < (const node &W) const {return val<W.val;} }a[N]; vector<node>v[N]; struct Node {int l,r;int sum,smax,lmax,rmax; }tr[N*4];void pushup(Node &a,Node &l,Node &r) {a.sum=l.sum+r.sum;a.lmax=max(l.lmax,l.sum+r.lmax);a.rmax=max(r.rmax,r.sum+l.rmax);//a.smax=max(max(l.smax,r.smax),l.rmax+r.lmax); }void pushup(int u) {pushup(tr[u],tr[u<<1],tr[u<<1|1]); }void build(int u,int l,int r,int c) {if(l==r) {tr[u]={l,r,c,c,c,c};return;}tr[u].l=l,tr[u].r=r;int mid=(tr[u].l+tr[u].r)>>1;build(u<<1,l,mid,c),build(u<<1|1,mid+1,r,c);pushup(u); }void modify(int u,int x,int c) {if(tr[u].l==x&&tr[u].r==x) tr[u]={x,x,c,c,c,c};else{int mid=(tr[u].l+tr[u].r)>>1;if(x<=mid) modify(u<<1,x,c);else modify(u<<1|1,x,c);pushup(u);} }Node query(int u,int l,int r) {if(l>r) return {0,0,0,0,0,0};if(tr[u].l>=l&&tr[u].r<=r) return tr[u];int mid=(tr[u].l+tr[u].r)>>1;if(r<=mid) return query(u<<1,l,r);else if(l>mid) return query(u<<1|1,l,r);else {Node a,b,ans;a=query(u<<1,l,r);b=query(u<<1|1,l,r);pushup(ans,a,b);return ans;} }int main() {cin>>n;for(int i=1;i<=n;i++) {scanf("%d",&a[i].val);a[i].id=i;v[a[i].val].pb(a[i]);}build(1,1,n,-1);for(int i=1;i<=n;i++) {for(auto x:v[i]) modify(1,x.id,1);for(auto x:v[i]) {Node r=query(1,x.id+1,n),l=query(1,1,x.id-1);ans[x.id]=max(ans[x.id],(l.rmax)/2);ans[x.id]=max(ans[x.id],(r.lmax)/2);ans[x.id]=max(ans[x.id],(l.rmax+r.lmax)/2);//if(x.id==7) cout<<l.lmax<<' '<<r.lmax<<endl;}//if(i==2) cout<<ans[4]<<endl;//if(i==4) cout<<ans[2]<<endl; }build(1,1,n,-1);for(int i=n;i>=1;i--) {for(auto x:v[i]) modify(1,x.id,1);for(auto x:v[i]) {Node r=query(1,x.id+1,n),l=query(1,1,x.id-1);ans[x.id]=max(ans[x.id],(l.rmax+1)/2);ans[x.id]=max(ans[x.id],(r.lmax+1)/2);ans[x.id]=max(ans[x.id],(l.rmax+r.lmax+1)/2);//if(x.id==1) cout<<i<<' '<<r.lmax<<' '<<l.rmax<<endl;//if(i==2) cout<<r.lmax<<endl;}//if(i==2) cout<<ans[4]<<endl;}for(int i=1;i<=n;i++) printf("%d ",ans[i]); puts("");return 0; }

總結

以上是生活随笔為你收集整理的Codeforces Round #727 (Div. 2) F. Strange Array 线段树 + 区间合并 + 排序优化的全部內容,希望文章能夠幫你解決所遇到的問題。

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