• CF480E Parking Lot


    传送门

    题目翻译给的很清楚w

    这题官方给的算法是分治,但是说实话我真的不知道它和分治有什么关系……

    有一个很正常的思路是先把所有修改都加上,之后先计算出来最小的情况(这个很简单,dp一下即可),之后再逐步考虑修改有什么影响。

    首先如果一次修改对答案有影响的话,那么更优的矩形一定是跨过这个障碍所在的一列的。如果当前的答案是ans的话,那么我们相当于要统计,对于障碍所在的这一列,有没有一个长为ans+1的区间,使得其每一行的左右两端能拓展到ans+1.

    这个好像和以前的矩形dp非常像……考虑用到悬线法,记录每个点能向左右最远拓展几个格子。之后对于合法的正方形,我们只要在这一列从上向下,用单调队列维护一下当前能拓展到的最远左右距离是多少,把与当前行距离超过ans的都去掉,之后更新答案即可。

    一开始像悬线法一样处理一下左右拓展的距离,之后对于每一个修改暴力更新一下就好了。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define fr friend inline
    #define y1 poj
    #define mp make_pair
    #define pr pair<int,int>
    #define fi first
    #define sc second
    #define pb push_back
    #define lowbit(x) x & (-x)
    
    using namespace std;
    typedef long long ll;
    const int M = 2005;
    const int INF = 1000000009;
    const double eps = 1e-7;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    struct node
    {
       int x,y;
    }a[M];
    
    int n,m,k,le[M][M],ri[M][M],q[M],dp[M][M],cur,ans[M],kx,ky,head,tail,tmp[M];
    bool pd[M][M];
    char s[M];
    
    void init()
    {
       rep(i,1,n)
       rep(j,1,m)
       {
          if(pd[i][j]) dp[i][j] = 0;
          else dp[i][j] = min(dp[i-1][j-1],min(dp[i][j-1],dp[i-1][j])) + 1;
          cur = max(cur,dp[i][j]);
       }
       rep(i,1,n)
       rep(j,1,m) pd[i][j] ? le[i][j] = 0 : le[i][j] = le[i][j-1] + 1;
       rep(i,1,n)
       per(j,m,1) pd[i][j] ? ri[i][j] = 0 : ri[i][j] = ri[i][j+1] + 1;
    }
    
    bool check(int d)
    {
       head = 1,tail = 0;
       rep(i,1,n)
       {
          while(head <= tail && le[q[tail]][ky] >= le[i][ky]) tail--;
          q[++tail] = i;
          while(head <= tail && q[head] <= i - d) head++;
          tmp[i] = le[q[head]][ky];
       }
       head = 1,tail = 0;
       rep(i,1,n)
       {
          while(head <= tail && ri[q[tail]][ky] >= ri[i][ky]) tail--;
          q[++tail] = i;
          while(head <= tail && q[head] <= i - d) head++;
          tmp[i] += ri[q[head]][ky] - 1;
       }
       rep(i,d,n) if(tmp[i] >= d) return 1;
       return 0;
    }
     
    int main()
    {
       n = read(),m = read(),k = read();
       rep(i,1,n)
       {
          scanf("%s",s+1);
          rep(j,1,m) if(s[j] == 'X') pd[i][j] = 1;
       }
       rep(i,1,k) a[i].x = read(),a[i].y = read(),pd[a[i].x][a[i].y] = 1;
       init();
       per(i,k-1,1)
       {
          ans[i+1] = cur;
          kx = a[i+1].x,ky = a[i+1].y,pd[kx][ky] = 0;
          rep(j,1,m) pd[kx][j] ? le[kx][j] = 0 : le[kx][j] = le[kx][j-1] + 1;
          per(j,m,1) pd[kx][j] ? ri[kx][j] = 0 : ri[kx][j] = ri[kx][j+1] + 1;
          while(check(cur+1)) cur++;
       }
       ans[1] = cur;
       rep(i,1,k) printf("%d
    ",ans[i]); 
       return 0;
    }
    View Code
  • 相关阅读:
    TCP的发送系列 — 发送缓存的管理(二)
    TCP的发送系列 — 发送缓存的管理(一)
    TCP的发送系列 — tcp_sendmsg()的实现(二)
    TCP的发送系列 — tcp_sendmsg()的实现(一)
    YTU 2618: B 求类中数据成员的最大值-类模板
    YTU 2617: B C++时间类的运算符重载
    YTU 2616: A代码完善--简易二元运算
    YTU 2615: AB编程题--世界杯小组赛
    YTU 2614: A代码完善--系统日期
    YTU 2611: A代码完善--向量的运算
  • 原文地址:https://www.cnblogs.com/captain1/p/10086521.html
Copyright © 2020-2023  润新知