求大神路过指导ZOJ3597 Hit the Target!

WAd的不行了, 我的做法式线段树,  先把靶子每q个编号, 再把每p把枪能打到的靶子编号插入线段树, 统计最大值, 不断的插入, 统计, 删除......   就是不对啊, 求大神路过指导......

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>

#define pause cout << " press any key to continue...", cin >> chh
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)

using namespace std;
int chh;

const int N = 50005, M = 100005;

struct Node {
    int u, v;
    bool operator < (const Node& arg0) const {
        if (u != arg0.u) return u < arg0.u;
        return v < arg0.v;
    }
} edge[M];

int T, n, m, p, q;
int a[M << 2], b[M << 2], head[N];
Node c[M];

void init(int k, int s, int t) {
    int mid = (s + t) >> 1;
    a[k] = b[k] = 0;
    if (s == t) return;
    init(k << 1, s, mid);
    init(k << 1 | 1, mid + 1, t);
}

void push_down(int k) {
    if (b[k] == 0) return;
    a[k << 1] += b[k], b[k << 1] += b[k];
    a[k << 1 | 1] += b[k], b[k << 1 | 1] + b[k];
    b[k] = 0;
}

void update(int k, int s, int t, int x, int y, int f) {
    int mid = (s + t) >> 1;
    if (s >= x && t <= y) {
        a[k] += f, b[k] += f;
        return;
    }
    push_down(k);
    if (y <= mid) update(k << 1, s, mid, x, y, f);
    else if (x > mid) update(k << 1 | 1, mid + 1, t, x, y, f);
    else {
        update(k << 1, s, mid, x, mid, f);
        update(k << 1 | 1, mid + 1, t, mid + 1, y, f);
    }
    a[k] = max(a[k << 1], a[k << 1 | 1]);
}

int main() {
    //file_r("in.txt");
    //file_w("out.txt");
    int i, j, k, h, v, l, r, x, y, e;
    double ans;
    scanf("%d", &T);
    while (T--) {
        //cout << "cas= " << ++cas << endl;
        scanf("%d%d%d%d", &n, &m, &p, &q);
        scanf("%d", &k);
        for (i = 0; i < k; i++) scanf("%d%d", &edge[i].u, &edge[i].v);
        sort(edge, edge + k);
        for (i = 0; i < k; i++) {
            v = edge[i].v;
            c[i].u = v - q + 1 >= 1 ? v - q + 1 : 1;
            c[i].v = v + q - 1 <= m ? v : m - q + 1;
        }
        e = 1;
        for (i = 1; i < k; i++) {
            if (edge[i].u != edge[i - 1].u) {
                c[e] = c[i], edge[e++] = edge[i];
                continue;
            }
            c[i].u = max(c[i].u, c[i - 1].v + 1);
            if (c[i].u <= c[i].v) c[e] = c[i], edge[e++] = edge[i];
        }
        //puts("Fuck");
        //for (i = 0; i < e; i++) printf("%d %d\n", edge[i].u, edge[i].v); pause;
        fill(head + 1, head + n + 1, -1);
        head[edge[0].u] = 0;
        //printf("e= %d", e), pause;
        for (i = 1; i < e; i++)
            if (edge[i].u != edge[i - 1].u) head[edge[i].u] = i;
        //for (i = 0; i < e; i++) printf("%d %d %d\n", edge[i].u, c[i].u, c[i].v);
        //for (i = 1; i <= n; i++) printf("%d ", head[i]); pause;
        init(1, 1, m - q + 1);
        for (i = 1; i < p; i++) {
            if (head[i] == -1) continue;
            for (j = head[i]; edge[j].u == i && j < e; j++){
                update(1, 1, m - q + 1, c[j].u, c[j].v, 1);
               // printf("ass= %d %d a[1]= %d", c[j].u, c[j].v, a[1]), pause;
            }
        }
        ans = 0;
        for (i = p; i <= n; i++) {
           // printf("i= %d %d", i, head[i]), pause;
            if (head[i] != -1) {
                for (j = head[i]; edge[j].u == i && j < e; j++){
                    update(1, 1, m - q + 1, c[j].u, c[j].v, 1);
                   // printf("add= %d %d a[1]= %d", c[j].u, c[j].v, a[1]), pause;
                }
            }
            ans += a[1];
            //printf("ans = %d", a[1]), pause;
            if (head[i - p + 1] != -1) {
                for (j = head[i - p + 1]; edge[j].u == i - p + 1 && j < e; j++)
                    update(1, 1, m - q + 1, c[j].u, c[j].v, -1);
            }
        }
        ans /= n - p + 1;
        printf("%.2lf\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值