codevs 4927 線段樹練習5 題解
阿新 • • 發佈:2018-11-12
一、題目:
二、思路:
這將是我NOIP2018前的最後一篇題解,從現在到NOIP我將進入總複習階段。祝NOIP rp++。
那麼這道題顯然會有兩個標記,一個add標記,一個set標記。那麼怎樣才能使這兩個標記互不影響呢?
我們規定一個順序,當set標記打過來時,我們首先將add標記清零,再打set標記。
改了改程式碼風格,具體請見部落格置頂文章。
三、程式碼:
/* * @Author: 岸芷汀蘭 * @Date: 2018-10-15 22:11:37 * @LastEditors: 岸芷汀蘭 * @LastEditTime: 2018-10-15 23:13:52 * @Description: 4927 of codevs */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #define LL long long #define mem(s,v) memset(s,v,sizeof(s)) using namespace std; template<class Type> inline Type read(void) { Type x = 0, f = 1; char ch = getchar(); while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return f * x; } const int maxn = 100005; int n, m; LL a[maxn]; struct Segment_Tree { #define lson (o << 1) #define rson (o << 1 | 1) LL set[maxn << 2], add[maxn << 2], sum[maxn << 2], maxv[maxn << 2], minv[maxn << 2], len[maxn << 2]; inline void pushup(int o) { sum[o] = sum[lson] + sum[rson]; maxv[o] = max(maxv[lson], maxv[rson]); minv[o] = min(minv[lson], minv[rson]); } inline void build(int o, int l, int r) { len[o] = r - l + 1; add[o] = sum[o] = maxv[o] = minv[o] = 0; set[o] = -1; if (l == r) { sum[o] = a[l]; maxv[o] = a[l]; minv[o] = a[l]; return; } int mid = (l + r) >> 1; build(lson, l, mid); build(rson, mid + 1, r); pushup(o); } inline void Add(int o,int v){ add[o]+=v; sum[o]+=len[o]*v; minv[o]+=v;maxv[o]+=v; return; } inline void Set(int o,int v){ set[o]=v;add[o]=0; sum[o]=len[o]*v; maxv[o]=minv[o]=v; return; } inline void pushdown(int o){ if(set[o]!=-1){ Set(lson,set[o]);Set(rson,set[o]); set[o]=-1; } if(add[o]){ Add(lson,add[o]);Add(rson,add[o]); add[o]=0; } return; } inline void Update(int o,int l,int r,int ql,int qr,int k,LL v){ if(ql<=l&&r<=qr){ if(k==1){//add Add(o,v);return; } else{//set Set(o,v);return; } } pushdown(o); int mid=(l+r)>>1; if(ql<=mid)Update(lson,l,mid,ql,qr,k,v); if(qr>mid)Update(rson,mid+1,r,ql,qr,k,v); pushup(o); } inline LL query(int o,int l,int r,int ql,int qr,int k){ if(ql<=l&&r<=qr){ switch(k){ case 1://sum return sum[o]; case 2://max return maxv[o]; case 3://min return minv[o]; } } pushdown(o); int mid=(l+r)>>1;LL ans=0; switch(k){ case 1://sum if(ql<=mid)ans+=query(lson,l,mid,ql,qr,k); if(qr>mid)ans+=query(rson,mid+1,r,ql,qr,k); return ans; case 2://max ans=-0x3f3f3f3f3f3f3f3f; if(ql<=mid)ans=max(ans,query(lson,l,mid,ql,qr,k)); if(qr>mid)ans=max(ans,query(rson,mid+1,r,ql,qr,k)); return ans; case 3://min ans=0x3f3f3f3f3f3f3f3f; if(ql<=mid)ans=min(ans,query(lson,l,mid,ql,qr,k)); if(qr>mid)ans=min(ans,query(rson,mid+1,r,ql,qr,k)); return ans; } } }T; int main() { n = read<int>(); m = read<int>(); for (register int i = 1; i <= n; ++i) { a[i] = read<LL>(); } T.build(1, 1, n); for (register int i = 1; i <= m; ++i) { string s; cin >> s; if (s == "add") { int l = read<int>(), r = read<int>(); LL c = read<LL>(); T.Update(1, 1, n, l, r, 1, c); } else if (s == "set") { int l = read<int>(), r = read<int>(); LL c = read<LL>(); T.Update(1, 1, n, l, r, 2, c); } else if (s == "sum") { int l = read<int>(), r = read<int>(); printf("%lld\n", T.query(1, 1, n, l, r, 1)); } else if (s == "max") { int l = read<int>(), r = read<int>(); printf("%lld\n", T.query(1, 1, n, l, r, 2)); } else if (s == "min") { int l = read<int>(), r = read<int>(); printf("%lld\n", T.query(1, 1, n, l, r, 3)); } } return 0; }