zoukankan      html  css  js  c++  java
  • [POI2008]KUP

    Description
    给一个(n imes n)的地图,每个格子有一个价格,找一个矩形区域,使其价格总和位于[k,2k]

    Input
    输入k n(n<2000)和一个(n imes n)的地图

    Output
    输出矩形的左上和右下的列-行坐标或NIE

    Sample Input 1
    4 3
    1 1 1
    1 9 1
    1 1 1

    Sample Output 1
    NIE

    Sample Input 2
    8 4
    1 2 1 3
    25 1 2 1
    4 20 3 3
    3 30 12 2

    Sample Output 2
    2 1 4 2

    HINT
    1<=k<=10^9 每个价格都是不大于2$ imes$10^9的非负整数


    首先如果单点有就直接输出,否则的话,我们把<k的点给标记一下,那么我们可以发现,答案必然是标记的点所构成的极大子矩阵中的子矩阵。所以我们对标记的点求一次极大子矩阵,然后看情况不断对矩阵删减即可。如果不会极大子矩阵的话可以参考该国家队论文王知昆--浅谈用极大化思想解决最大子矩形问题

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x>=10)     print(x/10);
    	putchar(x%10+'0');
    }
    const int N=2e3;
    int map[N+10][N+10],L[N+10][N+10],R[N+10][N+10],l[N+10][N+10],r[N+10][N+10],h[N+10][N+10];
    ll sum[N+10][N+10];
    int k,n;
    ll get(int x1,int y1,int x2,int y2){return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];}
    void write(int x1,int y1,int x2,int y2){
    	while (get(x1,y1,x2,y2)>2*k){
    		if (get(x1+1,y1,x2,y2>=k))	x1++;
    		else	if (get(x1,y1,x2-1,y2)>=k)	x2--;
    		else	if (get(x1,y1+1,x2,y2)>=k)	y1++;
    		else	if (get(x1,y1,x2,y2-1)>=k)	y2--;
    	}
    	printf("%d %d %d %d
    ",y1,x1,y2,x2);
    	exit(0);
    }
    int main(){
    	k=read(),n=read();
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=n;j++){
    			map[i][j]=read();
    			if (map[i][j]>=k&&map[i][j]<=2*k){
    				printf("%d %d %d %d
    ",j,i,j,i);
    				return 0;
    			}
    			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+map[i][j];
    		}
    	}
    	for (int i=1;i<=n;i++){
    		int nowl=0;
    		for (int j=1;j<=n;j++)	map[i][j]<k?L[i][j]=nowl+1:nowl=j;
    	}
    	for (int i=1;i<=n;i++){
    		int nowr=n+1;
    		for (int j=n;j>=1;j--)	map[i][j]<k?R[i][j]=nowr-1:nowr=j;
    	}
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=n;j++){
    			if (map[i][j]>2*k)	continue;
    			if (i==1||map[i-1][j]>2*k)	h[i][j]=1,l[i][j]=L[i][j],r[i][j]=R[i][j];
    			else	h[i][j]=h[i-1][j]+1,l[i][j]=max(l[i-1][j],L[i][j]),r[i][j]=min(r[i-1][j],R[i][j]);
    		}
    	}
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=n;j++){
    			if (map[i][j]<=k<<1){
    				int x1=i-h[i][j]+1,y1=l[i][j],x2=i,y2=r[i][j];
    				if (get(x1,y1,x2,y2)>=k)	write(x1,y1,x2,y2);
    			}
    		}
    	}
    	printf("NIE
    ");
    	return 0;
    }
    
  • 相关阅读:
    Windows性能计数器应用
    Azure Oracle Linux VNC 配置
    Azure 配置管理系列 Oracle Linux (PART6)
    Azure 配置管理系列 Oracle Linux (PART5)
    Azure 配置管理系列 Oracle Linux (PART4)
    Azure 配置管理系列 Oracle Linux (PART3)
    Azure 配置管理系列 Oracle Linux (PART2)
    vagrant多节点配置
    docker基本操作
    LINUX开启允许对外访问的网络端口命令
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/9035688.html
Copyright © 2011-2022 走看看