作者部落格:
正解:線段樹
解題報告:
這道題是一道線段樹的神題,需要我們支援區間開方、區間加法和區間求和操作。
關鍵是對於開方操作的處理,考慮如果乙個區間最大值等於最小值(即全都相等),那麼就可以直接開方,然後區間賦值。
否則就往下遞迴處理,知道發現整個區間相等再區間操作。
上述做法在這樣的資料下會被卡tle:8、9、8、9,這樣每次都會達到最壞複雜度。
但是我們發現他們如果開方之後的減少的值是相同的,也就是說這種情況我們可以特判,變成區間減法操作,這樣就可以保證複雜度。
為了降低程式設計複雜度,可以把區間賦值操作變成區間減法,也就是負數的區間減法,會方便很多。
另外,標記可持久化+不下傳,可以大大減小常數。
//it is made by ljh2000#include #include #include #include #include #include #include #include #include #define lc root<<1
#define rc root<<1|1
using namespace std;
typedef long long ll;
const int maxn = 100011;
int n,m,c[maxn],ql,qr,val;
ll ans;
struct nodea[maxn*3];
inline void jia(node &tmp,ll y)
inline int getint()
inline void update(int root)
inline void build(int root,int l,int r)
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
update(root);
}inline void add(int root,int l,int r)
int mid=(l+r)>>1;
if(ql<=mid) add(root<<1,l,mid);
if(qr>mid) add(root<<1|1,mid+1,r);
update(root);
}inline void sqr(int root,int l,int r,ll tag)
else if((a[root].max==a[root].min+1) && cp1==cp2)
} int mid=(l+r)>>1;
if(ql<=mid) sqr(lc,l,mid,tag+a[root].tag);
if(qr>mid) sqr(rc,mid+1,r,tag+a[root].tag);
update(root);
}inline void query(int root,int l,int r,ll tag)
int mid=(l+r)>>1;
if(ql<=mid) query(lc,l,mid,tag+a[root].tag);
if(qr>mid) query(rc,mid+1,r,tag+a[root].tag);
}inline void work()
else if(type==2)
else }}
int main()
uoj 228 基礎資料結構練習題
第一次看到這題大概在這裡 2016多校聯合 反正當時也沒什麼想法,表示有區間加好難受。題解並不難,維護每個區間最值 和,當乙個區間開根後所有值都一樣就直接賦值,否則遞迴。存在一種特例 3 4 3 4 3 4 3 4 3,開根後1 2 1 2 1 2 1 2 1.2 3 4 3 4 3 4 3 4 3...
題解 uoj228 基礎資料結構練習題
題目大意 給定乙個序列,要求支援區間加 區間開根號 區間求和操作。線段樹,我們可以像往常一樣判斷區間內的數是否都相等,如果相等就直接區間賦值,否則暴力遞迴下去。但是開根號還有一種特殊情況 3 4 3 4 3 4 開完根號1 2 1 2 1 2 同時加上2又變回了3 4 3 4 3 4 就給乙個完全平...
UOJ228 基礎資料結構練習題(線段樹)
給定序列,要求資瓷區間加 區間開根 區間求和。用線段樹維護最大值 最小值 和。如果 max max min min max max min min 那麼一起處理 打上區間減標記即可。時間複雜度?我太菜了,不知道。au hany01 prob uoj228 基礎資料結構練習題 date jul 31s...