[SDOI2010]粟粟的书架

前50分就开两个数组,一个sum[i][j][k],表示1,1到i,j大于k的和,num[i][j][k]表示个数,二分一下就好
后50分用主席树,主席树上二分

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(6e6 + 10);

IL ll Read(){
    char c = '%'; ll x = 0, z = 1;
    for(; c > '9' || c < '0'; c = getchar()) if(c == '-') z = -1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
    return x * z;
}


int R, C, M;
namespace Score1{
    int p[210][210], sum[210][210][1010], num[210][210][1010], Max;

    IL void Work(){
        for(RG int i = 1; i <= R; ++i)
            for(RG int j = 1; j <= C; ++j)
                p[i][j] = Read(), Max = max(p[i][j], Max);
        for(RG int k = 1; k <= Max; ++k)
            for(RG int i = 1; i <= R; ++i)
                for(RG int j = 1; j <= C; ++j){
                    sum[i][j][k] = sum[i - 1][j][k] + sum[i][j - 1][k] - sum[i - 1][j - 1][k];
                    num[i][j][k] = num[i - 1][j][k] + num[i][j - 1][k] - num[i - 1][j - 1][k];
                    if(p[i][j] >= k) ++num[i][j][k], sum[i][j][k] += p[i][j];
                }
        while(M--){
            RG int x1, y1, x2, y2, h, l = 1, r = Max, ans = 0;
            x1 = Read(); y1 = Read(); x2 = Read(); y2 = Read(); h = Read();
            while(l <= r){
                RG int mid = (l + r) >> 1;
                RG int calc = sum[x2][y2][mid] - sum[x2][y1 - 1][mid] - sum[x1 - 1][y2][mid] + sum[x1 - 1][y1 - 1][mid];
                if(calc >= h) ans = mid, l = mid + 1;
                else r = mid - 1;
            }
            if(!ans){  puts("Poor QLW"); continue;  }
            RG int s = sum[x2][y2][ans] - sum[x2][y1 - 1][ans] - sum[x1 - 1][y2][ans] + sum[x1 - 1][y1 - 1][ans];
            RG int f = num[x2][y2][ans] - num[x2][y1 - 1][ans] - num[x1 - 1][y2][ans] + num[x1 - 1][y1 - 1][ans];
            f -= (s - h) / ans;
            printf("%d\n", f);
        }
    }
}

namespace Score2{
    int rt[_], sz[_], sum[_], ls[_], rs[_], cnt;

    IL void Build(RG int &x, RG int l, RG int r){
        x = ++cnt;
        if(l == r) return;
        RG int mid = (l + r) >> 1;
        Build(ls[x], l, mid); Build(rs[x], mid + 1, r);
    }

    IL void Modify(RG int &x, RG int l, RG int r, RG int v){
        sz[++cnt] = sz[x]; sum[cnt] = sum[x]; ls[cnt] = ls[x]; rs[cnt] = rs[x];
        x = cnt; sz[cnt]++; sum[x] += v;
        if(l == r) return;
        RG int mid = (l + r) >> 1;
        if(v <= mid) Modify(ls[x], l, mid, v);
        else Modify(rs[x], mid + 1, r, v);
    }

    IL int Query(RG int A, RG int B, RG int l, RG int r, RG int h){
        if(l == r) return (h + l - 1) / l;
        RG int mid = (l + r) >> 1, s = sum[rs[A]] - sum[rs[B]];
        if(s >= h) return Query(rs[A], rs[B], mid + 1, r, h);
        return Query(ls[A], ls[B], l, mid, h - s) + sz[rs[A]] - sz[rs[B]];
    }

    IL void Work(){
        Build(rt[0], 1, 1000);
        for(RG int i = 1, a; i <= C; ++i) a = Read(), rt[i] = rt[i - 1], Modify(rt[i], 1, 1000, a);
        while(M--){
            RG int h, l, r;
            Read(); l = Read(); Read(); r = Read(); h = Read();
            if(sum[rt[r]] - sum[rt[l - 1]] < h) puts("Poor QLW");
            else printf("%d\n", Query(rt[r], rt[l - 1], 1, 1000, h));
        }
    }
}

int main(RG int argc, RG char *argv[]){
    R = Read(); C = Read(); M = Read();
    if(R > 1) Score1::Work();
    else Score2::Work();
    return 0;
}
posted @ 2018-01-04 18:41  Cyhlnj  阅读(191)  评论(0编辑  收藏  举报