大分块 WA 求助
查看原帖
大分块 WA 求助
519384
Link_Cut_Y楼主2022/12/28 20:42

好不容易不 TLETLE 了,但是都 WAWA 力。。。

分块 + 分块前缀和,时间复杂度 O(qn)O(q \sqrt n) ,空间复杂度 O(100n+n)O(100 \sqrt n + n)

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath> 
#define rep(i, a, b) for (int i = (a); i <= (b); i ++ )
#define rop(i, a, b) for (int i = (a); i < (b); i ++ )
#define dep(i, a, b) for (int i = (a); i >= (b); i -- )
#define dop(i, a, b) for (int i = (a); i > (b); i -- )

using namespace std;

using LL = long long;
using PII = pair<int, int>;
using PLL = pair<LL, LL>;

const int N = 200010, M = (int)sqrt(N) + 10;
const int INF = 0x3f3f3f3f;
int len, n, m;

struct Node {
	int w, s;
}p[N], s[M];
int pre[M][101];

struct Blocks {
	int l = INF, r = -INF;
	int cnt[101]; Node sum;
	int maxn = -INF, minn = INF;
}b[M];

int get(int x) {
	return (int)x / len + 1;
}

double query1(int l, int r) {
	int lc = get(l), rc = get(r);
    int ans = 0, len = 0;
    if (lc == rc) {
        for (int i = l; i <= r; i ++ )
        	ans += p[i].w * p[i].s, len += p[i].s;
        return (double)ans / len;
    }
    for (int i = l; i <= b[lc].r; i ++ ) ans += p[i].w * p[i].s, len += p[i].s;
    for (int i = r; i >= b[rc].l; i -- ) ans += p[i].w * p[i].s, len += p[i].s;
    ans += s[rc - 1].w - s[lc].w, len += s[rc - 1].s - s[lc].s;
    return (double)ans / len;
}

int query2(int l, int r) {
	int cnt[101] = {0};
	int lc = get(l), rc = get(r);
	int answ = -INF, ans;
    if (lc == rc) {
        for (int i = l; i <= r; i ++ )
            cnt[p[i].w] += p[i].s;
        for (int i = 0; i <= 100; i ++ )
        	if (cnt[i] > answ) answ = cnt[i], ans = i;
        return ans;
    }
    for (int i = l; i <= b[lc].r; i ++ ) cnt[p[i].w] += p[i].s;
    for (int i = r; i >= b[rc].l; i -- ) cnt[p[i].w] += p[i].s;
    for (int i = 0; i <= 100; i ++ )
    	cnt[i] += pre[rc - 1][i] - pre[lc][i];
    for (int i = 0; i <= 100; i ++ )
        	if (cnt[i] > answ) answ = cnt[i], ans = i;
    return ans;
}

int query3(int l, int r) {
	int maxn = -INF, minn = INF;
	int lc = get(l), rc = get(r);
    if (lc == rc) {
        for (int i = l; i <= r; i ++ )
            maxn = max(maxn, p[i].w),
            minn = min(minn, p[i].w);
        return maxn - minn;
    }
    for (int i = l; i <= b[lc].r; i ++ )
		maxn = max(maxn, p[i].w),
        minn = min(minn, p[i].w);
    for (int i = r; i >= b[rc].l; i -- )
    	maxn = max(maxn, p[i].w),
        minn = min(minn, p[i].w);
    for (int i = lc + 1; i <= rc - 1; i ++ )
    	maxn = max(maxn, b[i].maxn),
    	minn = min(minn, b[i].minn);
    return maxn - minn;
}

int main() {
	scanf("%d%d", &n, &m);
	len = (int)sqrt(n);
	for (int i = 1; i <= n; i ++ )
		scanf("%d", &p[i].w);
	for (int i = 1; i <= n; i ++ )
		scanf("%d", &p[i].s);
	
	for (int i = 1; i <= n; i ++ ) {
		int c = get(i);
        b[c].l = min(b[c].l, i);
        b[c].r = max(b[c].r, i);
        b[c].maxn = max(b[c].maxn, p[i].w);
        b[c].minn = min(b[c].minn, p[i].w);
        b[c].sum.w += p[i].w, b[c].sum.s += p[i].s;
        b[c].cnt[p[i].w] += p[i].s;
    }
    for (int i = get(1); i <= get(n); i ++ )
    	s[i].w = s[i - 1].w + p[i].w, 
    	s[i].s = s[i - 1].s + p[i].s;
    for (int i = get(1); i <= get(n); i ++ )
		for (int j = 0; j <= 100; j ++ )
			pre[i][j] = pre[i - 1][j] + b[i].cnt[j];
		
    while (m -- ) {
    	int op, l, r;
    	scanf("%d%d%d", &op, &l, &r);
    	if (op == 1) printf("%.2lf\n", query1(l, r));
    	if (op == 2) printf("%d\n", query2(l, r));
    	if (op == 3) printf("%d\n", query3(l, r));
	}
	
	return 0;
}
2022/12/28 20:42
加载中...