分類:data structure
[bzoj4373算術天才⑨與等差數列]
算術天才⑨非常喜歡和等差數列玩耍。
有一天,他給了你乙個長度為n的序列,其中第i個數為a[i]。
他想考考你,每次他會給出詢問l,r,k,問區間[l,r]內的數從小到大排序後能否形成公差為k的等差數列。
當然,他還會不斷修改其中的某一項。
為了不被他鄙視,你必須要快速並正確地回答完所有問題。
注意:只有乙個數的數列也是等差數列。
輸入格式:
第一行包含兩個正整數n,m(1<=n,m<=300000),分別表示序列的長度和操作的次數。
第二行包含n個整數,依次表示序列中的每個數ai。
接下來m行,每行一開始為乙個數op,
若op=1,則接下來兩個整數x,y(1<=x<=n,0<=y<=10^9),表示把a[x]修改為y。
若op=2,則接下來三個整數l,r,k(1<=l<=r<=n,0<=k<=10^9),表示乙個詢問。
在本題中,x,y,l,r,k都是經過加密的,都需要異或你之前輸出的yes的個數來進行解密。
現在假設查詢的區間為[l
,r],
令(w=
r−l+
1,a0
=min
v,aw
=max
v),根據等差數列的性質,可得:
用線段樹維護區間最小值minv,區間最大值maxv,區間和sum1,區間平方和sum2。
另外,求sum2的過程中還要注意溢位。
#include
using
namespace
std;
typedef
long
long ll;
typedef
long
double lb;
typedef pair pii;
typedef pairpll;
typedef
vector
vi;
const
int inf = 0x3f3f3f3f;
const ll infl = 0x3f3f3f3f3f3f3f3fll;
#define lson l, mid, (rt << 1)
#define rson mid + 1, r, (rt << 1 | 1)
#define debug(x) cout << "[" << x << "]" << endl
const
int maxn = 300000 + 5;
int n, m;
ll a[maxn];
struct node
node(ll minv, ll maxv, ll sum1, ll sum2) : minv(minv), maxv(maxv), sum1(sum1), sum2(sum2) {}
} nd[maxn << 2];
inline
void pushup(node& rt, const node& lch, const node& rch)
void build(int l, int r, int rt)
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(nd[rt], nd[rt << 1], nd[rt << 1 | 1]);
}void update(const
int& p, const ll& x, int l, int r, int rt)
int mid = (l + r) >> 1;
if (p <= mid) update(p, x, lson);
else update(p, x, rson);
pushup(nd[rt], nd[rt << 1], nd[rt << 1 | 1]);
}node query(const
int& l, const
int& r, int l, int r, int rt)
int mid = (l + r) >> 1;
node lop(-1, -1, 0, 0), rop(-1, -1, 0, 0);
if (l <= mid) lop = query(l, r, lson);
if (r > mid) rop = query(l, r, rson);
if (lop.maxv == -1) return rop;
if (rop.maxv == -1) return lop;
return node(min(lop.minv, rop.minv), max(lop.maxv, rop.maxv), lop.sum1 + rop.sum1, lop.sum2 + rop.sum2);
}inline
bool check(ll l, ll r, ll k, const node& e)
int main() else
node e = query(l, r, 1, n, 1);
if (k == 0)
// printf("[%lld %lld %lld %lld]", e.minv, e.maxv, e.sum1, e.sum2);
if (check(l, r, k, e)) puts("yes"), ++cnt;
else
puts("no");}}
#ifdef ___local_wonzy___
cout
<< "time elapsed: "
<< 1.0 * clock() / clocks_per_sec * 1000
<< " ms."
<< endl;
#endif // ___local_wonzy___
return
0;}
bzoj4373 算術天才 與等差數列
bzoj4373 算術天才 與等差數列 給定乙個長為 n 的序列 a i 有 m 次操作 n,m leq3 times10 5,0 leq a i,k leq10 9 線段樹,hash 區間 l,r 所組成的等差數列首項為 min 末項為 max 公差為 k 可以考慮求出 l,r 和這個等差數列的h...
BZOJ1558 等差數列(線段樹)
題目大意 給出長為n n 100000 的序列v,q q 100000 次操作,每次對當前序列的 s,t 加上以a為首項b為公差的等差數列,或詢問當前序列 s,t 最少能劃分成多少段等差數列。題解 神奇的線段樹!等差數列差分之後值是相同的,便於統計最少劃分數,所以我們可以維護差分陣列。這樣修改操作就...
牛牛的等差數列 線段樹
這裡的突破口在於小於等於25且大於等於3的質數連乘在1e8左右,所以,我們可以在操作上,將其看作對1e8去求模,而不是對每個都進行預處理。時間複雜度 include include include include include include include include include inc...