bzoj 5103 [POI2018]Ró?norodno??

Posted asd123www

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 5103 [POI2018]Ró?norodno??相关的知识,希望对你有一定的参考价值。

  这个题没有想出来。。

  首先显然的一点是我们要对每种颜色做一次不重复的贡献计算。

  同种颜色的贡献就是矩形的并。从网上查了资料,矩形面积并用的是扫描线,那么这个我们也可以用扫描线了。

  我们考虑枚举横坐标,维护存在于当前横坐标的所有纵坐标的区间。一个性质是所有的矩形都是边长为k的正方形,那么在加入或删除一个区间时只可能影响到一个连续的区间。我们只需要对这个区间操作就行了。

  我用的set维护,因为bzoj开O2,所以比其他数据结构要快一些,但是没有bitset快,要跑47s,记得加上fread,这个题的读入量达到了9e6。

  前段时间好迷啊,bzoj号莫名上不去,只能借同学得了,看别人题解看不懂,浪费时间去看代码。。后来发现是自己没脑子了。。

 

#include <bits/stdc++.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define for1(a,b,i) for(int i=a;i<=b;++i)
#define FOR2(a,b,i) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
char xch,xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
inline int read() {
    int x=0,f=1;
    char ch=getc();
    while(ch<0|ch>9){if(ch==-)f=-1;ch=getc();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getc();}
    return x*f;
}

#define M 3005
#define N 100005
int n,m,K;
int a[M][M],size[N],sum[M][M];

struct node {
    int c;
    short x,y;
}buc[M*M];

struct point {
    short l,r;
    
    inline bool operator <(const point &a) const {
        return l<a.l;
    }
};

multiset <point> cc;
multiset <point>::iterator it,i;

inline void add_(int x,int l,int r,bool t) {
    if(x>n) return;
    if(!t) cc.insert((point){l,r});
    it=cc.lower_bound((point){l,r});
    int lx,rx;
    if(it==cc.begin()) lx=0;
    else i=it,i--,lx=(*i).r;
    i=it,i++;
    rx=i==cc.end()?m+1:(*i).l;
    ++lx,--rx;
    lx=max(lx,l),rx=min(rx,r);
    if(lx<=rx) {
        int k=t?-1:1;
        sum[x][lx]+=k;
        sum[x][rx+1]-=k;
    }
    if(t) cc.erase(it);
}

void solve_(int l,int r) {
    int h1=l-1,h2=l-1;
    while (h1<r&&h2<r) {
        int t0=buc[h1+1].x;
        int t1=buc[h2+1].x+K;
        if(t0<=t1) ++h1,add_(t0,buc[h1].y,buc[h1].y+K-1,0);
        if(t1<=t0) ++h2,add_(t1,buc[h2].y,buc[h2].y+K-1,1);
    }
    for1(h2+1,r,i) add_(buc[i].x+K,buc[i].y,buc[i].y+K-1,1);
    cc.clear();
}

int main () {
//    freopen("a.in","r",stdin);
    n=read(),m=read(),K=read();
    for1(1,n,i) for1(1,m,j) {
        a[i][j]=read();
        ++size[a[i][j]];
    }
    for1(1,100000,i) size[i]+=size[i-1];
    FOR2(n,1,i) FOR2(m,1,j) buc[size[a[i][j]]--]=(node){a[i][j],i,j};
    
    int l=1,r;
    while (l<=n*m) {
        r=l;
        while (buc[r+1].c==buc[l].c) ++r;
        solve_(l,r);
        l=r+1;
    }
    for1(1,n,i) {
        for1(1,m,j) sum[i][j]+=sum[i][j-1];
        for1(1,m,j) sum[i][j]+=sum[i-1][j];
    }
    ll tot=0;
    int ans=0;
    for1(K,n,i) for1(K,m,j) tot+=sum[i][j],ans=max(ans,sum[i][j]);
    printf("%d %lld
",ans,tot);
}

以上是关于bzoj 5103 [POI2018]Ró?norodno??的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 4725: [POI2017]Reprezentacje ró?nicowe

BZOJ5101[POI2018]Powód 并查集

bzoj5101[POI2018]Powód 并查集

bzoj5102[POI2018]Prawnicy 堆

[POI2018]Powód?

[POI2018]Powód?