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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CodeForces - 1326E Bombs(线段树+思维)

發布時間:2024/4/11 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1326E Bombs(线段树+思维) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個 n 的排列記為 p[ i ] ,現在有一個初始時為空的集合A,對于每個 i 遍歷 1 ~ n ,每次的操作如下:

  • 向集合中添加 p[ i ]
  • 如果位置 i 有炸彈,那么刪除掉集合中的最大值
  • 最后的答案就是保留在集合中的最大值

    接下來給出一個數組 q ,表示炸彈的位置,對于每個前綴炸彈給出答案,此處的前綴可以理解為:

  • 對于第一個答案,輸出不包含炸彈的的答案
  • 對于第二個答案,輸出包含炸彈 q[ 1 ] 的答案
  • 對于第三個答案,輸出包含炸彈 q[ 1?] , q[ 2 ] 的答案
  • 對于第四個答案,輸出包含炸彈 q[ 1 ] , q[ 2 ] , q[ 3 ] 的答案
  • .....
  • 對于第 n 個答案,輸出包含炸彈 q[ 1 ] , q[ 2 ] ... q[ n - 1 ] 的答案
  • 題目分析:比賽時感覺是線段樹,但自己維護的線段樹無法動態維護炸彈,因為每次添加的炸彈位置都是有大有小的,所以后續添加的炸彈很有可能會影響前面的決策,最后也是實力不夠,沒辦法解決這個問題

    賽后看了官方題解后也是思考了好久才勉強想明白,這里就大體說一下題解的意思吧

    因為動態維護炸彈比較困難,所以我們不妨將問題轉換為判斷答案是否合理,不難看出,隨著炸彈數量的增加,輸出的答案也會保持著非嚴格遞減的趨勢,所以我們從最大的答案開始不斷遞減,每次判斷是否合理即可

    轉換思路后,接下來的任務就是對于一個答案 x ,我們如何判斷他的合理性,如果答案 x 滿足條件,也就是所有炸彈都炸掉了極大值后,x 成為了最后集合中的最大值,這也就必須滿足所有大于 x 的值都被炸彈炸掉了,因為炸彈影響的范圍是 [ 1 , q[ i ] ] ,也就是會影響一個前綴,那么:

  • 右邊開始第一個 >?x 的數的右邊必須至少有一個炸彈
  • 右邊開始第二個 > x 的數的右邊必須至少有兩個炸彈
  • ....
  • 右邊開始第 k 個 > x 的數的右邊必須至少有 k 個炸彈
  • 如果滿足上述條件的話,就說明 > x 的所有數都會被炸彈炸掉,那么答案就肯定不可能是 x + 1 及以上了,只可能是 x 及以下

    此時我們可以用線段樹維護一下每個節點 右側炸彈的個數 - 右側大于 x 的數的個數 ,顯然對于每個節點而言,如果這個值大于等于 0 的話,那么 x + 1 及以上的答案是肯定不可能的,因為全都被炸彈炸沒了,我們就可以用一個 while 維護符合條件的答案了,又因為我們需要所有的答案都大于等于 0 時才滿足條件,所以我們只需要維護一下區間最小值就好了,最小值如果大于等于 0 的話,那么就說明所有節點都滿足這個條件了

    明白了思路后代碼寫起來就簡單多了,線段樹維護最小值+區間更新

    代碼:

    #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> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=3e5+100;int pos[N];struct Node {int l,r,mmin,lazy; }tree[N<<2];void build(int k,int l,int r) {tree[k].l=l;tree[k].r=r;tree[k].lazy=tree[k].mmin=0;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r); }void pushdown(int k) {if(tree[k].lazy){int lz=tree[k].lazy;tree[k].lazy=0;tree[k<<1].mmin+=lz;tree[k<<1].lazy+=lz;tree[k<<1|1].mmin+=lz;tree[k<<1|1].lazy+=lz;} }void update(int k,int l,int r,int val) {if(tree[k].l>r||tree[k].r<l)return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].mmin+=val;tree[k].lazy+=val;return;}pushdown(k);update(k<<1,l,r,val);update(k<<1|1,l,r,val);tree[k].mmin=min(tree[k<<1].mmin,tree[k<<1|1].mmin); }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n;scanf("%d",&n);build(1,1,n);for(int i=1;i<=n;i++){int num;scanf("%d",&num);pos[num]=i;}int ans=n+1;for(int i=1;i<=n;i++){int q;scanf("%d",&q);while(tree[1].mmin>=0){ans--;update(1,1,pos[ans],-1);}printf("%d ",ans);update(1,1,q,1);}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的CodeForces - 1326E Bombs(线段树+思维)的全部內容,希望文章能夠幫你解決所遇到的問題。

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