P4168 [Violet]蒲公英
神仙分块题?其实还是很简单的,res[i][j]表示第i块到第j块的众数,然后再用sum[i][j]表示前i块中j这个种类出现的次数,然后分块瞎搞就行了,感觉我写的十分简洁,好评(
//author Eterna #define Hello the_cruel_world! #pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<utility> #include<cmath> #include<climits> #include<deque> #include<functional> #include<complex> #include<numeric> #include<unordered_map> #define Pi acos(-1.0) #define ABS(x) ((x) >= 0 ? (x) : (-(x))) #define pb(x) push_back(x) #define lowbit(x) (x & -x) #define FRIN freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\in.txt", "r", stdin) #define FROUT freopen("C:\\Users\\Administrator.MACHENI-KA32LTP\\Desktop\\out.txt", "w", stdout) #define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define outd(x) printf("%d\n", x) #define outld(x) printf("%lld\n", x) #define il inline using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int maxn = 4e4; const int maxm = 2e2; const int INF = 0x7fffffff; const int mod = 1e9 + 7; const double eps = 1e-7; inline int read_int() { char c; int ret = 0, sgn = 1; do { c = getchar(); } while ((c < '0' || c > '9') && c != '-'); if (c == '-') sgn = -1; else ret = c - '0'; while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); return sgn * ret; } inline ll read_ll() { char c; ll ret = 0, sgn = 1; do { c = getchar(); } while ((c < '0' || c > '9') && c != '-'); if (c == '-') sgn = -1; else ret = c - '0'; while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); return sgn * ret; } int res[maxm + 5][maxm + 5], sum[maxm + 5][maxn + 5], cnt[maxn + 5]; int block, arr[maxn + 5], ID[maxn + 5]; int n, q, last; int m, pos[maxn + 5]; void pre_init() { for (int i = 1; i <= n; ++i)++sum[ID[i]][arr[i]]; for (int i = 1; i <= m; ++i)for (int j = 1; j <= ID[n]; ++j)sum[j][i] += sum[j - 1][i]; for (int i = 1; i <= ID[n]; ++i) { memset(cnt, 0, sizeof(cnt)); for (int j = (i - 1) * block + 1; j <= n; ++j) { int p = arr[j], k = res[i][ID[j - 1]]; ++cnt[p]; if (cnt[p] > cnt[k])res[i][ID[j]] = p; else if (cnt[p] == cnt[k] && p < k)res[i][ID[j]] = p; else res[i][ID[j]] = k; } } memset(cnt, 0, sizeof(cnt)); } int Query(int L, int R) { int ans = res[ID[L] + 1][ID[R] - 1], tot = max(0, sum[ID[R] - 1][ans] - sum[ID[L]][ans]); for (int i = L; i <= min(ID[L] * block, R); ++i) { int p = arr[i]; ++cnt[p]; int s = cnt[p] + max(0, (sum[ID[R] - 1][p] - sum[ID[L]][p])); if (s > tot) ans = p, tot = s; else if (s == tot && p < ans)ans = p; } if (ID[L] != ID[R]) { for (int i = (ID[R] - 1)*block + 1; i <= R; ++i) { int p = arr[i]; ++cnt[p]; int s = cnt[p] + max(0, (sum[ID[R] - 1][p] - sum[ID[L]][p])); if (s > tot) ans = p, tot = s; else if (s == tot && p < ans)ans = p; } } for (int i = L; i <= min(ID[L] * block, R); ++i)--cnt[arr[i]]; if (ID[L] != ID[R])for (int i = (ID[R] - 1) * block + 1; i <= R; ++i)--cnt[arr[i]]; return ans; } int main() { n = read_int(), q = read_int(); block = ceil(sqrt(n)); for (int i = 1; i <= n; ++i) pos[i] = arr[i] = read_int(), ID[i] = (i - 1) / block + 1; sort(pos + 1, pos + 1 + n); m = unique(pos + 1, pos + 1 + n) - pos - 1; for (int i = 1; i <= n; ++i)arr[i] = lower_bound(pos + 1, pos + 1 + m, arr[i]) - pos; pre_init(); for (int i = 1; i <= q; ++i) { int l = read_int(), r = read_int(); l = (l + last - 1) % n + 1, r = (r + last - 1) % n + 1; if (l > r)swap(l, r); last = pos[Query(l, r)]; outd(last); } return 0; }
posted on 2019-03-19 12:05 Eterna_King 阅读(132) 评论(0) 编辑 收藏 举报