牛客練習賽56D 小翔和泰拉瑞亞(線段樹 思維)

2021-10-01 21:10:03 字數 1653 閱讀 4412

給定乙個n元素陣列,你有m個操作,每次操作可以選擇乙個區間[li,ri],將這個區間內的數減少vi,你可以選擇其中一些進行操作,問你最後可以得到的最大值與最小值的差是多少?

因為每個操作是對於區間而言,我們不可能去遍歷每個區間,所以需要更好的策略。

又因為題中說的是最大值與最小值的差,所以我們可以考慮固定一端,選擇另一端。

於是,我們列舉每個位置i,然後選擇操作,讓i盡可能的小(也就是如果區間x包括了點i,我們就選擇區間x),這樣點i能夠到達理想的最小值,此時我們再查詢整個區間的最大值,就是一種可行的答案了,最後答案取所以位置的最大值就完了。

因為乙個點可能被很多個區間覆蓋,我們並不是暴力加,在從左往右遍歷的過程中,在每個區間的左端點l插入這個區間,在區間的右端點r+1處刪除這個區間,這樣每個區間只會被update兩次,就能更新到每個位置i啦。

#include using namespace std;

typedef long long ll;

const int maxn=2e5+10;

struct treenodetree[maxn<<2];

ll a[maxn];

void push_up(int root)

void build(int root,int l,int r)

int mid=(l+r)>>1;

build(root<<1,l,mid);

build(root<<1|1,mid+1,r);

push_up(root);

}void push_down(int root)

}void update(int root,int l,int r,int v)

push_down(root);

int mid=(tree[root].l+tree[root].r)>>1;

if(r<=mid)

else if(l>mid)

else

push_up(root);

}ll query(int root,int l,int r,int opt)

push_down(root);

int mid=(tree[root].l+tree[root].r)>>1;

if(r<=mid)

else if(l>mid)

else

else

}}struct segseg[maxn];

vectorl[maxn];

vectorr[maxn];

int cmp(const seg a,const seg b)

inline ll readll()

signed main()

build(1,1,n);

for(int i=1;i<=m;i++)

sort(seg+1,seg+m+1,cmp);

for(int i=1;i<=m;i++)

ll ans=0;

for(int i=1;i<=n;i++)

for(int j=0;jll now=query(1,i,i,2);

ll maxx=query(1,1,n,1);

ans=max(ans,maxx-now);

}printf("%lld\n",ans);

return 0;

}

牛客練習賽56 D 小翔和泰拉瑞亞(線段樹)

題目描述 小翔愛玩泰拉瑞亞 一天,他碰到了一幅地圖。這幅地圖可以分為n列,第i列的高度為hi,他認為這個地圖不好看,決定對它進行改造。小翔又學會了m個魔法,實施第i個魔法可以使地圖的第li列到第ri列每一列的高度減少wi,每個魔法只能實施一次,魔法的區間可能相交或包含。小翔認為,一幅地圖中最高的一列...

小翔和泰拉瑞亞

題目描述 小翔愛玩泰拉瑞亞 一天,他碰到了一幅地圖。這幅地圖可以分為n列,第i列的高度為hi,他認為這個地圖不好看,決定對它進行改造。小翔又學會了m個魔法,實施第i個魔法可以使地圖的第li列到第ri列每一列的高度減少wi,每個魔法只能實施一次,魔法的區間可能相交或包含。小翔認為,一幅地圖中最高的一列...

牛客練習賽56 小魂和他的數列

題目鏈結 給出乙個數列,讓求長度為k的嚴格遞增子串行有多少個 怎麼做呢?顯然dp 這個是很好想的 for int i 1 i n i for int i 2 i m i 這個dp顯然tle 所以 當時沒有做出來。做到這裡不會做了。想不到怎麼優化。顯然在最裡面的那個迴圈的作用是字首和 小於a i 的位...