CodeForces 1393B Applejack and Storages

A p p l e j a c k Applejack Applejack a n d and and S t o r a g e s Storages Storages

由于本菜鸡很笨,并没有想到什么简单的思路,所以有幸在时间内用权值线段树水过,u1s1我的思维确实垃圾

思路:
利用权值线段树求区间第k小,首先我们只需要知道三个变量(最大相同数量 d m dm dm,次大相同数量 d s ds ds,次次大 d k dk dk),那么就可以写了,显然这题你用排序肯定不行了,那样最坏时间复杂度是 O ( q l o g ( q + n ) ) O(qlog(q+n)) O(qlog(q+n)),显然会TLE,那么权值线段树可以帮你实现 O ( q l o g ( q + n ) ) O(qlog(q+n)) O(qlog(q+n)),具体思路请看下图:
CodeForces 1393B Applejack and Storages_第1张图片
CodeForces 1393B Applejack and Storages_第2张图片
CodeForces 1393B Applejack and Storages_第3张图片
具体操作看代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
//#define ll long long
const ll N = 1e3 + 5;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair p;
//priority_queue, greater

> m; // ll sum[maxn], a[maxn]; ll max(ll a, ll b) { return a > b ? a : b; } ll min(ll a, ll b) { return a < b ? a : b; } ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; } ll lcm(ll a, ll b) { return a * b / gcd(a, b); } map<ll, ll> mp; ll ksm(ll a, ll b) { a %= mod; ll ans = 1ll; while (b) { if (b & 1) ans = (ans * a) % mod; a = (a * a) % mod; b >>= 1ll; } return ans; } // ll dp[105][16005]; // string p = "abacaba"; // queue qk, q; //vector vec; // ll sumx[maxn], sumy[maxn], sumk[maxn]; int cnt; map<int, int> p; struct node { int ls, rs, sum; } tr[maxn * 32]; void inser(int &k, int L, int R, int pos, int w) { if (!k) k = ++cnt; tr[k].sum += w; if (L == R) return; int mid = L + R >> 1; if (mid >= pos) inser(tr[k].ls, L, mid, pos, w); else inser(tr[k].rs, mid + 1, R, pos, w); } int query(int k, int L, int R, int ik) { if (L == R) return L; int sk = tr[tr[k].ls].sum; int mid = L + R >> 1; if (sk >= ik) return query(tr[k].ls, L, mid, ik); else return query(tr[k].rs, mid + 1, R, ik - sk); } int main() { ios::sync_with_stdio(false); cin.tie(0); //ll t, n, ans; // scanf("%lld", &t); // cin >> t; // while (t--) // { p.clear(); int n, k = 0, Q, x, res = 0; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i], p[a[i]]++; for (int i = 1; i <= n; i++) { if (!vis[a[i]]) inser(k, -maxn, maxn, p[a[i]], 1), vis[a[i]] = 1, res++; } cin >> Q; while (Q--) { char c; cin >> c >> x; if (c == '-') { inser(k, -maxn, maxn, p[x], -1), p[x]--; if (p[x] == 0) vis[x] = 0, res--; else inser(k, -maxn, maxn, p[x], 1); } else { if (!vis[x]) { p[x]++, res++, vis[x] = 1; inser(k, -maxn, maxn, p[x], 1); } else { inser(k, -maxn, maxn, p[x], -1), p[x]++; inser(k, -maxn, maxn, p[x], 1); } } //cout << "***" << n << "***" << endl; int dm = query(k, -maxn, maxn, res); int ds = query(k, -maxn, maxn, res - 1); int dk = query(k, -maxn, maxn, res - 2); //cout << dm << ' ' << ds << ' ' << dk << endl; if (dm >= 8) { cout << "YES" << endl; continue; } if (dm >= 4 && ds >= 4) { cout << "YES" << endl; continue; } if (dm >= 4 && ((ds >= 2 && (dm - 4) >= 2) || dk >= 2)) { cout << "YES" << endl; continue; } cout << "NO" << endl; } // } }

你可能感兴趣的:(ACM刷题题解)