粟粟的书架(主席树+二维前缀和)

粟粟的书架

一下子做了两个题?
题意:一个问题求区间前K大的和,另一个问题求矩形内前K大的和。

思路:

  1. 前一个问题直接上主席树+二分搞定
  2. 后一个问题由于数据范围比较小,用 c n t [ i ] [ j ] [ k ] cnt[i][j][k] cnt[i][j][k]记录前缀矩形中大于等于 k k k的数有多少个,用 p r e [ i ] [ j ] [ k ] pre[i][j][k] pre[i][j][k]记录前缀矩形中大于等于 k k k的数的和。利用这两个东西套两个二分即可
  3. 代码清晰易懂,就不讲了

题面描述

#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}

const int maxn = 5e5+10;
const int mod = 1e9+7;
const double eps = 1e-9;

int n, m, t, tot;
int h[maxn], T[maxn<<5];
int sz[maxn<<5], L[maxn<<5], R[maxn<<5];
ll sum[maxn<<5];

void update(int x, int l, int r, int pre, int &now) {
    now=++tot;
    L[now]=L[pre], R[now]=R[pre], sz[now]=sz[pre]+1, sum[now]=sum[pre]+x;
    if(l==r) return;
    int m=(l+r)/2;
    if(x<=m) update(x,l,m,L[pre],L[now]);
    else update(x,m+1,r,R[pre],R[now]);
}

ll qksum(int k, int x, int y, int l, int r) {
    if(l==r) return k*l;
    int s=sz[R[y]]-sz[R[x]];
    int m=(l+r)/2;
    if(s>=k) return qksum(k,R[x],R[y],m+1,r);
    else return sum[R[y]]-sum[R[x]]+qksum(k-s,L[x],L[y],l,m);
}

ll pre[205][205][1005];
int cnt[205][205][1005];

inline int QAQ(int k, int x1, int y1, int x2, int y2) {
    return cnt[x2][y2][k]-cnt[x2][y1-1][k]-cnt[x1-1][y2][k]+cnt[x1-1][y1-1][k];
}

inline ll qsum(int k, int x1, int y1, int x2, int y2) {
    int l=1, r=1001, mid=(l+r)/2;
    while(l<r) {
        if(QAQ(mid,x1,y1,x2,y2)<k) r=mid;
        else l=mid+1;
        mid=(l+r)/2;
    }
    int cnt=QAQ(mid,x1,y1,x2,y2);
    ll sum=pre[x2][y2][mid]-pre[x2][y1-1][mid]-pre[x1-1][y2][mid]+pre[x1-1][y1-1][mid];
    return sum+=1ll*(k-cnt)*(mid-1);
}

int main() {
    //ios::sync_with_stdio(false); cin.tie(0);
    n=read(), m=read(), t=read();
    if(n==1) { //前一个问题,主席树
        for(int i=1; i<=m; ++i) update(read(),1,1000,T[i-1],T[i]);
        for(int i=0; i<t; ++i) {
            int x1=read(), y1=read()-1, x2=read(), y2=read(), H=read();
            int l=1, r=y2-y1+1, mid=(l+r)/2;
            while(l<r) {
                if(qksum(mid,T[y1],T[y2],1,1000)<H) l=mid+1;
                else r=mid;
                mid=(l+r)/2;
            }
            if(mid==y2-y1+1) printf("Poor QLW\n");
            else printf("%d\n", mid);
        }
    }
    else { //后一个问题,后一个问题二维前缀和
        for(int i=1; i<=n; ++i) {
            for(int j=1; j<=m; ++j) {
                int k=read();
                pre[i][j][k]=k, cnt[i][j][k]=1;
            }
        }
        for(int i=1; i<=n; ++i) {
            for(int j=1; j<=m; ++j) {
                for(int k=1000; k; --k)
                    pre[i][j][k]+=pre[i][j][k+1], cnt[i][j][k]+=cnt[i][j][k+1];
                for(int k=1000; k; --k) {
                    pre[i][j][k]+=pre[i-1][j][k]+pre[i][j-1][k]-pre[i-1][j-1][k];
                    cnt[i][j][k]+=cnt[i-1][j][k]+cnt[i][j-1][k]-cnt[i-1][j-1][k];
                }
            }
        }
        for(int i=0; i<t; ++i) {
            int x1=read(), y1=read(), x2=read(), y2=read(), H=read();
            int tot=(x2-x1+1)*(y2-y1+1);
            int l=1, r=tot+1, mid=(l+r)/2;
            while(l<r) {
                if(qsum(mid,x1,y1,x2,y2)<H) l=mid+1;
                else r=mid;
                mid=(l+r)/2;
            }
            if(mid==tot+1) printf("Poor QLW\n");
            else printf("%d\n", mid);
        }
    }
}
全部评论

相关推荐

粗心的雪碧不放弃:纯学历问题,我这几个月也是一直优化自己的简历,后来发现优化到我自己都觉得牛逼的时候,发现面试数量也没有提升,真就纯学历问题
点赞 评论 收藏
分享
像好涩一样好学:这公司我也拿过 基本明确周六加班 工资还凑活 另外下次镜头往上点儿
点赞 评论 收藏
分享
11-12 15:08
已编辑
长江大学 算法工程师
3年前的秋招季,原来只是一个新手教程罢了。2个月之前,我,一个9本华五硕,手上一个Offer都没有。从来没想到会遇到这样的场面,大环境退化了,自己的价值也没有在这段经历中有所提升。实验室里同届的人也都至少面的很顺,有个保底,而我还在挣扎求生。但结果只是惨淡,算不上完败:上周五我收到了小红书的oc,同时最近也接到了华为的保温电话,这标志着互联网公司的沟通基本都有了个结果。是时候该回顾一下过去的心得了,我想以一位网友给我的一份回复,一个教训作为切入点。一个教训也就在秋招最困难的这段时间,我发帖吐槽了一位让我感觉不舒服的面试官,于是受到了一位“工作两年多的网友”的教训。虽然他已经删除这段话,但我很在...
牛客73841773号:怀着复杂的心情读了好几遍,丝毫没感受到作者“读书人的傲慢”,反而,透过这段逻辑清晰、有理有据的文字,我感受到了一种读书人特有的温厚的力量,这显然是名校熏陶和个人修养综合作用的结果。这种力量,让我想起过去一百多年里许多名校学子所展现出的,自强不息的进取精神,通透达观的处世心态,悲智双运的人文关怀。这位作者,你清醒的智慧、清晰的远见、不卑不亢的态度和公正的自我认知,一定会让你在不久的将来作出正确的选择,过上幸福的人生。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务