首页 > 其他分享 >Codeforces Round #815 (Div. 2) E. Misha and Paintings

Codeforces Round #815 (Div. 2) E. Misha and Paintings

时间:2022-08-24 01:01:08浏览次数:56  
标签:map 颜色 Paintings int max Misha Codeforces 正方形 左上角

人生中第一个AC的codeforces题,大概

太难了,光是看答案就看了整整一下午,最后还是在b站上搜到讲解视频才明白的。俺们阿B真的是太厉害啦

这道题首先容易看出当矩阵中数字个数小于或等于所需要的个数时,直接输出他们的差即可。剩下的就是判断大于的情况。

这种情况的处理方法还多亏了大佬室友。像是个脑筋急转弯。但对我来说显然不是 可以证明在这种情况下,操作数至多为2,不是2就是1。证明方法是构造,总算知道tag里的构造算法是怎么回事了 首先从左上角开始往右下角画正方形,在正方形里填上同一种数字(颜色),直到整个方阵里的颜色种类恰好多余要求种类数,正方形再大一点就删过了。之后从这个正方形的右下的元素开始向左上方扩展正方形,由于和原来正方形重叠的部分已经被删过了,所以新的正方形每扩大一点,删除的颜色就会多2。也就是说用这样的删法,最终的颜色种类数与所要求的数字最多只会相差1,而这个1是可以通过恰当选择填充的颜色来避免的。这也就证明了操作数最多两步。

问题进而转化为能否一步完成。这个问题可以在n3解决。方法是先预处理数据,记录每种颜色在矩阵中最左上的坐标和最右下的坐标,框出一个矩形。然后枚举正方形的边长,从1到n。对于每一个边长,枚举每种颜色,根据颜色的边界坐标确定正方形要想框住所有的这种颜色,左上角定点所能在的范围,是一个矩形。只要所选的正方形的左上角顶点位于这个范围内,就能删除一种颜色。具体而言,一种颜色的左上角确定了正方形的右下界,颜色的右下角确定了正方形的左上界。下一步是根据正方形的界做标记。这里不能对这个矩形范围内的所有元素进行修改,因为这是n2的复杂度。这里应该用二维懒标记(2D lazy update)或者说二维差分。在范围的左上角加一,在右上角右边减一,在左下角下边减一,在右下角的右下加一。之后用计算前缀和的方法还原更新后的整个方阵。计算二维前缀和的方法是先扫描每一行,元素值为其行前缀和,再以此类推扫描每一列。还原后再用n^2时间扫描整个方阵,如果有一个元素满足n-k(颜色选择剩余部分已有的颜色)或者n-k+1(颜色选择不存在的颜色),则说明可以用一步完成,否则就只能两步完成了。

代码:

#include <iostream>

using namespace std;

bool m[250005];

struct color{
    int r_min = 501, r_max = -1, c_min = 501, c_max = -1;
} map[250005];

int main(){
    int n, k;
    cin >> n >> k;
    int cat = 0;
    for(int i = 0; i<n; ++i){
        for(int j = 0; j<n; ++j){
            int x;
            cin >> x;
            if(!m[x]){
                m[x] = 1;
                ++cat;
            }
            if(i<map[x].r_min)
                map[x].r_min = i;
            if(i>map[x].r_max)
                map[x].r_max = i;
            if(j<map[x].c_min)
                map[x].c_min = j;
            if(j>map[x].c_max)
                map[x].c_max = j;
        }
    }
    if(cat<=k){
        cout << k-cat;
        return 0;
    }
    else{
        for(int i = 1; i<=n; ++i){
            int tmp[501][501] = {0};
            for(int j = 1; j<250005; ++j){
                if(m[j]&&map[j].r_max-map[j].r_min+1<=i&&map[j].c_max-map[j].c_min+1<=i){
                    int ul_r = (map[j].r_max-i+1<0?0:map[j].r_max-i+1);
                    int ul_c = (map[j].c_max-i+1<0?0:map[j].c_max-i+1);
                    int br_r = map[j].r_min+1;
                    int br_c = map[j].c_min+1;
                    tmp[ul_r][ul_c]++;
                    tmp[ul_r][br_c]--;
                    tmp[br_r][ul_c]--;
                    tmp[br_r][br_c]++;
                }
            }
            for(int j = 0; j<=n-i; ++j){
                int sum = 0;
                for(int t = 0; t<=n-i; ++t){
                    sum+=tmp[j][t];
                    tmp[j][t] = sum;
                }
            }
            for(int j = 0; j<=n-i; ++j){
                int sum = 0;
                for(int t = 0; t<=n-i; ++t){
                    sum+=tmp[t][j];
                    tmp[t][j] = sum;
                    if(sum==cat-k||sum==cat-k+1){
                        cout << 1;
                        return 0;
                    }
                }
            }
        }
    }
    cout << 2;
    return 0;
}

标签:map,颜色,Paintings,int,max,Misha,Codeforces,正方形,左上角
From: https://www.cnblogs.com/salty-pretzel001/p/16618372.html

相关文章

  • Codeforces Round #783 (Div. 2) E (证明+构造)
    一般这种题我们都是先推导下界再来构造那我们假设我们当前放置了k位半皇后我们只考虑横竖被吃掉并且贪心的(类似于八皇后的选择)横竖都不重叠我们把他固定在左上角的kk......
  • Codeforces Round #292 (Div. 2) C. Drazil and Factorial(思维)
    https://codeforces.com/contest/515题目大意:给我们一个长度为n的数字a定义F(a)=a里面每一位数的阶层总乘积让我们求最大的x,需要满足F(x)=f(a)并且x中没有0和1input4......
  • Codeforces Round #638 (Div. 2) B. Phoenix and Beauty(构造/思维)
    https://codeforces.com/contest/1348/problem/B如果一个数组的所有长度为k的子数组的和相同,那么这个数组就是美丽的。数组的子数组是任何连续元素的序列。Phoenix目前......
  • *Codeforces Round #363 (Div. 1) A. Vacations(状态机)
    https://codeforces.com/contest/698/problem/AVasya有n天假期!Vasya知道关于这n天中每一天的以下信息:那家健身房是否开门,以及那天是否在互联网中进行了比赛。第i天有四个......
  • CodeForces-1715D 2+ doors
    2+doors贪心位与位之间互不一向,因此考虑每个位进行考虑就行因为是或的关系,先考虑\(0\)的情况,如果出现\(0\),则两个数字的该位必然是\(0\)如果是\(1\)的情况,就考......
  • CodeForces-1715C Monoblock
    Monoblockdp先想想如何计算初始值\(dp[x]\)表示以第\(x\)个位置为\(r\),他的所有贡献状态转移:如果\(a_x=a_{x-1}\):\(dp[x]=dp[x-1]+1\),代表只增加了\(l......
  • CodeForces-1719D Burenka and Traditions
    BurenkaandTraditions贪心由于代价是向上取整的,因此可以直接考虑成两种方式:选择两个相邻的数,让他们同时异或上一个值选择一个数字,让他变成\(0\)由此可见,最多......
  • Codeforces Round #743 (Div. 2) B. Swaps(思维)
    https://codeforces.com/contest/1573/problem/B给定两个长度为n的数组,数组a和数组b数组a包含从1到2*n的任意顺序的奇数,数组b包含从1到2*n的任意偶数可执行的操作如下:......
  • Codeforces 1715E - Long Way Home
    又是废掉的一个div2啊第一次在学校熬夜打cf,开心还看到了自己最喜欢的斜率优化ohhh链接:E-LongWayHome看到那个平方就可以靠感觉认为是斜率优化了....感觉似不似......
  • Codeforces Round #816 (Div. 2)
    题面A.Crossmarket不妨设\(n\gem\),则答案为\(n+2(m-1)\)。特别地,\(n=1,m=1\)时答案为\(0\),注意特判。ViewCode#include<stdio.h>#include<algorithm>int......