CONTENT: 珂朵莉树/老司机树
DETAIL: 珂朵莉树/老司机树
BB
晚上喝咖啡,还睡了一会儿,然后整个晚上睡不着QAQ,莫名其妙通了个宵QAQ
jjdl(jiajun dl)去年提起过ODT这个东西,莫名神奇!
Introduction
Willem, Chtholly and Seniorious - CodeForces 896C
Description
给定四个操作:区间赋值、区间加、询问区间k大数、询问区间幂之和
保证数据随机
Solution
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node {
int l, r;
mutable ll val;
inline int len() const {
return r - l + 1;
}
bool operator < (const Node& b) const {
return l < b.l;
}
};
set<Node> st;
inline ll quickPow(ll a, int b, int MOD) {
ll ans = 1, base = a;
while(b) {
if(b & 1) {
ans = ans * base % MOD;
}
base = base * base % MOD;
b >>= 1;
}
return ans;
}
inline set<Node>::iterator split(int pos) {
auto it = st.lower_bound(Node{pos, 0, 0});
if(it != st.end() && it->l == pos) {
return it;
}
--it;
ll v = it->val;
int l = it->l, r = it->r;
st.erase(it);
st.insert(Node{l, pos - 1, v});
return st.insert(Node{pos, r, v}).first;
}
inline void assignVal(int l, int r, ll v) {
auto itr = split(r + 1), itl = split(l);
st.erase(itl, itr);
st.insert(Node{l, r, v});
}
inline void add(int l, int r, ll k) {
auto itr = split(r + 1), itl = split(l);
for(auto it = itl; it != itr; it++) {
it->val += k;
}
}
inline ll pow(int l, int r,int x, int y) {
auto itr = split(r + 1), itl = split(l);
ll sum = 0;
for(auto it = itl; it != itr; it++) {
sum = (sum + it->len() * quickPow(it->val % y, x, y) % y) % y;
}
return sum;
}
inline ll kth(int l, int r, int k) {
auto itr = split(r + 1), itl = split(l);
vector<pair<ll, int> > vec;
for(auto it = itl; it != itr; it++) {
vec.emplace_back(make_pair(it->val, it->len()));
}
sort(vec.begin(), vec.end());
for(auto ele : vec) {
k -= ele.second;
if(k <= 0) {
return ele.first;
}
}
return -1;
}
int seed;
inline int rnd() {
int ret = seed;
seed = ((ll)seed * 7 + 13) % 1000000007;
return ret;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m, vmax;
while(cin >> n >> m >> seed >> vmax) {
st.clear();
for(int i = 1; i <= n; i++) {
st.emplace(Node{i, i, rnd() % vmax + 1});
}
for(int i = 1; i <= m; i++) {
int op = (rnd() % 4) + 1;
int l = (rnd() % n) + 1;
int r = (rnd() % n) + 1;
int x, y;
if (l > r) {
swap(l, r);
}
if (op == 3)
x = (rnd() % (r - l + 1)) + 1;
else
x = (rnd() % vmax) + 1;
if (op == 4)
y = (rnd() % vmax) + 1;
if(op == 1) {
add(l, r, x);
} else if(op == 2) {
assignVal(l, r, x);
} else if(op == 3) {
cout << kth(l, r, x) << "\n";
} else {
cout << pow(l, r, x, y) << "\n";
}
}
cout.flush();
}
}
[SCOI2010]序列操作 - luogu P2572
Description
lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:
0 a b 把[a, b]区间内的所有数全变成0
1 a b 把[a, b]区间内的所有数全变成1
2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0
3 a b 询问[a, b]区间内总共有多少个1
4 a b 询问[a, b]区间内最多有多少个连续的1
对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?
Sample Input
10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
Sample Output
5
2
6
5
Solution
本题摆明了线段树,不过因为数据太水ODT可以过!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node {
int l, r;
mutable int val;
inline int len() const {
return r - l + 1;
}
bool operator < (const Node& b) const {
return l < b.l;
}
};
set<Node> st;
inline set<Node>::iterator split(int pos) {
auto it = st.lower_bound(Node{pos, 0, 0});
if(it != st.end() && it->l == pos) {
return it;
}
--it;
ll v = it->val;
int l = it->l, r = it->r;
st.erase(it);
st.insert(Node{l, pos - 1, v});
return st.insert(Node{pos, r, v}).first;
}
inline void assignVal(int l, int r, int v) {
auto itr = split(r + 1), itl = split(l);
st.erase(itl, itr);
st.insert(Node{l, r, v});
}
inline void reverse(int l, int r) {
auto itr = split(r + 1), itl = split(l);
for(auto it = itl; it != itr; it++) {
it->val ^= 1;
}
}
inline int sum(int l, int r) {
auto itr = split(r + 1), itl = split(l);
int res = 0;
for(auto it = itl; it != itr; it++) {
res += (it->val == 1) * it->len();
}
return res;
}
inline int calc(int l, int r) {
auto itr = split(r + 1), itl = split(l);
int res = 0, cnt = 0;
for(auto it = itl; it != itr; it++) {
if(it->val) {
cnt += it->len();
} else {
cnt = 0;
}
res = max(res, cnt);
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
while(cin >> n >> m) {
st.clear();
for(int i = 1, val; i <= n; i++) {
cin >> val;
st.emplace(Node{i, i, val});
}
while(m--) {
int op, l, r;
cin >> op >> l >> r;
l++;
r++;
switch(op) {
case 0:
case 1:
assignVal(l, r, op);
break;
case 2:
reverse(l, r);
break;
case 3:
cout << sum(l, r) << "\n";
break;
case 4:
cout << calc(l, r) << "\n";
break;
}
}
cout.flush();
}
}