I haven't written a question for a long time. I haven't written a question for the whole summer vacation. I decided to write it. So I picked this big question.
This is a problem with the standard mops algorithm, but for some reason, the data may be less than the minimum spanning tree in Manhattan. Specifically, it is divided by the Left endpoint of the query interval, and the block is sorted by the right endpoint, and then violent ......
It's really violent. It's too violent. I didn't believe that it could really pass out of O (N ^ 1.5) after AC.
In the block, the right endpoint increments. As the left endpoint is not ordered in the block, the left endpoint will shake. This is so violent ......
Code:
#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>#include <cmath>#define N 50001using namespace std;int n, m, kuai;struct sss{ int l, r; int num, ku;}ask[N];struct ss{ long long first, second;}ans[N];int colorcount[N], color[N];bool cmp(sss x, sss y) { return x.ku == y.ku ? x.r < y.r : x.ku < y.ku; }long long gcd(long long x, long long y){ if (!y) return x; return gcd(y, x%y);}int main(){ scanf("%d%d", &n, &m); kuai = (int)sqrt(n+0.5); for (int i = 1; i <= n; ++i) scanf("%d", &color[i]); for (int i = 1; i <= m; ++i) { scanf("%d%d", &ask[i].l, &ask[i].r); ask[i].num = i; ask[i].ku = ask[i].l / kuai + 1; } sort(ask+1, ask+1+m, cmp); int nowkuai = 0, nowr, nowl; long long nowans; for (int i = 1; i <= m; ++i) { if (ask[i].ku != nowkuai) { nowkuai = ask[i].ku; nowans = 0; nowl = ask[i].l; nowr = nowl-1; for (int j = 1; j <= n; ++j) colorcount[j] = 0; } for (int j = nowl; j < ask[i].l; ++j) { colorcount[color[j]] --; nowans -= colorcount[color[j]]; } for (int j = nowl-1; j >= ask[i].l; --j) { colorcount[color[j]] ++; nowans += colorcount[color[j]] - 1; } for (int j = nowr+1; j <= ask[i].r; ++j) { colorcount[color[j]] ++; nowans += colorcount[color[j]] - 1; } nowl = ask[i].l; nowr = ask[i].r; long long x = ask[i].r - ask[i].l + 1; x = (long long)x*(long long)(x-1)/2; long long d = gcd(x, nowans); if (nowans) { ans[ask[i].num].first = nowans/d; ans[ask[i].num].second = x/d; } else { ans[ask[i].num].first = 0; ans[ask[i].num].second = 1; } } for (int i = 1; i <= m; ++i) printf("%lld/%lld\n", ans[i].first, ans[i].second); return 0;}
Bzoj 2038 small Z so