zoukankan      html  css  js  c++  java
  • 【bzoj4241】 历史研究

    http://www.lydsy.com/JudgeOnline/problem.php?id=4241 (题目链接)

      看到题目就联想到了【bzoj2809】 Apio2012—dispatching。想了想权值分块+莫队,发现不好维护块内最值,又看了看80s的时间,于是怒水一发线段树+莫队,结果先WA后TLE,不断TLE,无论怎么改常数都不行,难道nlogn*sqrt(n)就是过不了吗!!不爽,蒯个题解,再见!

    题意

      求区间加权众数。

    solution

      貌似是分块,离散化之后,用mx[i][j]表示第i块到第j块的答案,cnt[i][j]表示前i块数字j的个数。

    代码

    // bzoj4241
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf 2147483640
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    inline LL getint() {
        int f,x=0;char ch=getchar();
        while (ch<='0' || ch>'9') {if (ch=='-') f=-1;else f=1;ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int maxn=100010;
    struct data {int w,id;}a[maxn];
    int b[maxn],pos[maxn],L[400],R[400],cnt[400][maxn],num[maxn],st[maxn];
    LL mx[400][400],ans;
    int n,m,block,tot,top;
    
    bool cmp(data a,data b) {
        return a.w<b.w;
    }
    LL cal(int l,int r) {
        LL ans=0;
        top=0;
        for (int i=l;i<=r;i++) {
            if (!num[b[i]]) st[++top]=b[i];
            num[b[i]]++;
            ans=max(ans,(LL)num[b[i]]*a[b[i]].w);
        }
        while (top) num[st[top--]]=0;
        return ans;
    }    
    void build() {
        block=sqrt(n);tot=(n-1)/block+1;
        for (int i=1;i<=n;i++) {
            pos[i]=(i-1)/block+1;
            if (!L[pos[i]]) L[pos[i]]=i;
            R[pos[i]]=i;
        }
        for (int i=1;i<=n;i++) cnt[pos[i]][b[i]]++;
        for (int i=2;i<=tot;i++)
            for (int j=1;j<=n;j++) cnt[i][j]+=cnt[i-1][j];
    }
    int main() {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i].w),a[i].id=i;
        sort(a+1,a+1+n,cmp);
        b[a[1].id]=1;
        for (int i=2;i<=n;i++) {
            if (a[i].w==a[i-1].w) b[a[i].id]=b[a[i-1].id];
            else b[a[i].id]=i;
        }
        build();
        for (int i=1;i<=tot;i++) {
            LL ans=0;
            memset(num,0,sizeof(num));
            for (int j=L[i];j<=n;j++) {
                num[b[j]]++;
                ans=max(ans,(LL)num[b[j]]*a[b[j]].w);
                if (j==R[pos[j]]) mx[i][pos[j]]=ans;
            }
        }
        memset(num,0,sizeof(num));
        for (int i=1;i<=m;i++) {
            int l,r;
            scanf("%d%d",&l,&r);
            ans=0;
            if (pos[l]==pos[r]) printf("%lld
    ",cal(l,r));
            else {
                ans=mx[pos[l]+1][pos[r]-1];
                top=0;
                for (int i=l;i<=R[pos[l]];i++)
                    if (!num[b[i]]) st[++top]=b[i],num[b[i]]=cnt[pos[r]-1][b[i]]-cnt[pos[l]][b[i]];
                for (int i=L[pos[r]];i<=r;i++)
                    if (!num[b[i]]) st[++top]=b[i],num[b[i]]=cnt[pos[r]-1][b[i]]-cnt[pos[l]][b[i]];
                for (int i=l;i<=R[pos[l]];i++) num[b[i]]++;
                for (int i=L[pos[r]];i<=r;i++) num[b[i]]++;
                while (top) {
                    ans=max(ans,(LL)a[st[top]].w*num[st[top]]);
                    num[st[top--]]=0;
                }
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    关于模态/非模态对话框不响应菜单的UPDATE_COMMAND_UI消息(对对WM_INITMENUPOPUP消息的处理)
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914625.html
Copyright © 2011-2022 走看看