本篇题解几题参考了AK大佬的题解,)因为本菜太lj了,orz大佬题解真的很漂亮
A、环鸽的CHONG
如果一个数在一段序列中只出现1次,那么我们可以从这个数分隔区间,在左右区间重复寻找是不是有数出现一次即可,递归处理。
这里的寻找遍历是不行的,时间复杂度太爆炸了,考虑散列表。开一个左边和右边上一次出现和下一次的位置。直接跳着找即可。
)这里顺带也问一句为什么用快读就错掉了,如果有大牛发现了,请告诉我一下,万分感谢,我把read函数贴出来,永远TLE,96.55%
#include <bits/stdc++.h> #pragma GCC optimize(2) #pragma GCC optimize(3) using namespace std; typedef long long ll; inline ll read() { ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } const int N = 2e5 + 7; int a[N], l[N], r[N]; unordered_map<int, int> mp; int dfs(int L, int R) { if (R - L <= 0) return true; int x = L, y = R, mid = -1; while (x <= y) { if (l[x] < L && R < r[x]) { mid = x; break; } if (l[y] < L && R < r[y]) { mid = y; break; } x++, y--; } if (mid == -1) return false; return dfs(L, mid - 1) && dfs(mid + 1, R); } int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", a + i); for (int i = 1; i <= n; ++i) { //记录当前位置字母的前一次出现位置,没出现为0 if (!mp[a[i]]) l[i] = 0; else l[i] = mp[a[i]]; mp[a[i]] = i; } mp.clear(); for (int i = n; i; --i) { if (!mp[a[i]]) r[i] = n + 1; else r[i] = mp[a[i]]; mp[a[i]] = i; } if (dfs(1, n)) puts("chong"); else puts("fuchong"); return 0; }
C、环鸽不会X点
后面改的签到题,直接判断最小行不行,如果大于最小再去判断奇偶性即可,奇数+奇数=偶数,只有奇数个奇数才可能是奇数
#include <bits/stdc++.h> #pragma GCC optimize(2) #pragma GCC optimize(3) using namespace std; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) typedef long long ll; const ll MOD = 1e9 + 7; inline ll read() { ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } inline void write(ll x) { if (!x) { putchar('0'); return; } char F[200]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); } inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; } ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } inline int lowbit(int x) { return x & (-x); } int main() { int T = read(); while (T--) { ll n = read(), k = read(); ll tmp = k * 3; if (n < tmp || ((n - k) & 1)) puts("No"); else puts("Yes"); } return 0; }
D、小C的棋王之路
刚刚看到大佬的题解,发现是珂朵莉树,混分巨兽,而且是合理的混分!太顶了,这题用珂朵莉就是码码板子就行了,如果你知道函数的作用。
先,在还有几个用处我一起放一下把,灵魂就是l,r之间才修改,不然别动它就行了,set去偷鸡!贼快乐,当然如果不被卡!
/* 骗分巨兽珂朵莉树 1区间加数,2区间乘数 3区间赋值,4区间第k小,5区间幂次和 直接快排 累加即可 */
#include <bits/stdc++.h> #pragma GCC optimize(2) #pragma GCC optimize(3) using namespace std; #define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) typedef long long ll; ll MOD; inline ll read() { ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } inline void write(ll x) { if (!x) { putchar('0'); return; } char F[200]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); } inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; } ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; } inline int lowbit(int x) { return x & (-x); } struct Node { int l, r; mutable ll val; Node(int l, int r = -1, ll val = 0) : l(l), r(r), val(val) {} bool operator <(const Node& rhs)const { return l < rhs.l; } }; set<Node> st; auto split(int x) { //灵魂!! auto it = st.lower_bound(x); if (it != st.end() && it->l == x) return it; --it; int l = it->l, r = it->r; ll val = it->val; st.erase(it); st.insert(Node(l, x - 1, val)); return st.insert(Node(x, r, val)).first; } void add(int l, int r, int x) { auto itr = split(r + 1), itl = split(l); for (; itl != itr; itl++) itl->val = (itl->val + x) % MOD; } void mul(int l, int r, int x) { auto itr = split(r + 1), itl = split(l); for (; itl != itr; itl++) itl->val = itl->val * x % MOD; } void assign(int l, int r, int x) { //赋值 auto itr = split(r + 1), itl = split(l); st.erase(itl, itr); st.insert(Node(l, r, x)); } ll query(int l, int r) { ll ans = 0; auto itr = split(r + 1), itl = split(l); for (; itl != itr; itl++) ans = (ans + itl->val * (itl->r - itl->l + 1) % MOD) % MOD; return ans; } int main() { int n = read(), m = read(); MOD = read(); for (int i = 1; i <= n; ++i) st.insert(Node(i, i, read())); ++n; st.insert(Node(n, n, 0)); //哨兵 while (m--) { int op = read(), l, r, x, k; if (op <= 3) { l = read(), r = read(), k = read(); if (op == 1) add(l, r, k); else if (op == 2) mul(l, r, k); else assign(l, r, k); } else if (op == 4) { x = read(); auto it = st.lower_bound(Node(n)); st.erase(it); //去掉哨兵 st.insert(Node(n, n, x)); ++n; st.insert(Node(n, n, 0)); //新加哨兵 } else { l = read(), r = read(); write(query(l, r)), putchar(32); } } return 0; }