| 
 | 1 | +#pragma GCC optimize ("O3")  | 
 | 2 | +#include <bits/stdc++.h>  | 
 | 3 | +#include "got.h"  | 
 | 4 | +using namespace std;  | 
 | 5 | + | 
 | 6 | +ifstream in{"input.txt"};  | 
 | 7 | +ofstream out{"output.txt"};  | 
 | 8 | +#ifdef DEBUG  | 
 | 9 | +template<class A,class B>ostream&operator<<(ostream&o,const pair<A,B>&p){cout<<"("<<p.first<<", "<<p.second<<")";return o;}  | 
 | 10 | +template<class T,typename=typename enable_if<!is_same<T, string>::value,decltype(*begin(declval<T>()))>::type>ostream&operator<<(ostream&o,const T&v){cout<<"[";for(auto it=v.begin();it!=v.end();++it){if(it!=v.begin()){cout<<", ";}cout<<*it;}cout<<"]";return o;}  | 
 | 11 | +void deb(){cout<<"\n";}template<class T,class...Ts>void deb(const T&t,const Ts&...args){cout<<t;if(sizeof...(args)!=0){cout<<" ";}deb(args...);}  | 
 | 12 | +#else  | 
 | 13 | +#define deb(...)  | 
 | 14 | +#endif  | 
 | 15 | +#define cout Do not use cout!!!  | 
 | 16 | +#define cin Do not use cin!!!  | 
 | 17 | + | 
 | 18 | +int R,C;  | 
 | 19 | +vector<int> grid;  | 
 | 20 | + | 
 | 21 | +struct UFDS {  | 
 | 22 | + uint16_t par;  | 
 | 23 | + uint16_t remaining = numeric_limits<uint16_t>::max();  | 
 | 24 | + | 
 | 25 | + bool hasWantedSize(){  | 
 | 26 | + return remaining==0;  | 
 | 27 | + }  | 
 | 28 | + | 
 | 29 | + bool isUsed(int i){  | 
 | 30 | + return par!=i || remaining!=numeric_limits<uint16_t>::max();  | 
 | 31 | + }  | 
 | 32 | +};  | 
 | 33 | +static_assert(sizeof(UFDS) == 4);  | 
 | 34 | + | 
 | 35 | +struct Sol {  | 
 | 36 | + vector<UFDS> mem;  | 
 | 37 | + int satisfied=0;  | 
 | 38 | + | 
 | 39 | + Sol() : mem(R*C) {  | 
 | 40 | + for(int i=0;i<R*C;++i){  | 
 | 41 | + mem[i].par=i;  | 
 | 42 | + }  | 
 | 43 | + }  | 
 | 44 | + | 
 | 45 | + int root(int i) {  | 
 | 46 | + if(mem[i].par==i) return i;  | 
 | 47 | + return mem[i].par = root(mem[i].par);  | 
 | 48 | + }  | 
 | 49 | + | 
 | 50 | + void merge(int i, int j) {  | 
 | 51 | + int ri=root(i);  | 
 | 52 | + int rj=root(j);  | 
 | 53 | + if (ri==rj) {  | 
 | 54 | + return;  | 
 | 55 | + }  | 
 | 56 | + | 
 | 57 | + // if(mem[rj].remaining>mem[ri].remaining){  | 
 | 58 | + // swap(ri,rj);  | 
 | 59 | + // }  | 
 | 60 | + // //now ri has the highest size  | 
 | 61 | + | 
 | 62 | + mem[ri].remaining-=(grid[rj]-mem[rj].remaining);  | 
 | 63 | + if (mem[ri].hasWantedSize()) {  | 
 | 64 | + satisfied+=grid[ri];  | 
 | 65 | + }  | 
 | 66 | + mem[rj].par=ri;  | 
 | 67 | + }  | 
 | 68 | + | 
 | 69 | + void print() {  | 
 | 70 | + for(int i=0;i<R*C;++i){  | 
 | 71 | + if (i!=0) {  | 
 | 72 | + if (i%C==0){  | 
 | 73 | + out<<"\n";  | 
 | 74 | + } else {  | 
 | 75 | + out<<" ";  | 
 | 76 | + }  | 
 | 77 | + }  | 
 | 78 | + int ri = root(i);  | 
 | 79 | + if (mem[ri].hasWantedSize()) {  | 
 | 80 | + out<<grid[ri];  | 
 | 81 | + } else {  | 
 | 82 | + out<<0;  | 
 | 83 | + }  | 
 | 84 | + }  | 
 | 85 | + out<<"\n***"<<endl;  | 
 | 86 | + }  | 
 | 87 | +#ifdef DEBUG  | 
 | 88 | + void debprint() {  | 
 | 89 | + for(int i=0;i<R*C;++i){  | 
 | 90 | + if (i!=0) {  | 
 | 91 | + if (i%C==0){  | 
 | 92 | + cerr<<"\n";  | 
 | 93 | + } else {  | 
 | 94 | + cerr<<" ";  | 
 | 95 | + }  | 
 | 96 | + }  | 
 | 97 | + int ri = root(i);  | 
 | 98 | + | 
 | 99 | + if(mem[ri].remaining==numeric_limits<uint16_t>::max()){  | 
 | 100 | + cerr<<"(_,_)";  | 
 | 101 | + } else {  | 
 | 102 | + cerr<<"("<<grid[ri]<<","<<mem[ri].remaining<<")";  | 
 | 103 | + }  | 
 | 104 | + }  | 
 | 105 | + cerr<<"\n***"<<endl;  | 
 | 106 | + }  | 
 | 107 | +#else  | 
 | 108 | + inline void debprint() {}  | 
 | 109 | +#endif  | 
 | 110 | +};  | 
 | 111 | + | 
 | 112 | +vector<int> neighbors(int i) {  | 
 | 113 | + vector<int> res;  | 
 | 114 | + if (i%C != 0) {  | 
 | 115 | + res.push_back(i-1);  | 
 | 116 | + }  | 
 | 117 | + if (i%C != C-1) {  | 
 | 118 | + res.push_back(i+1);  | 
 | 119 | + }  | 
 | 120 | + if (i/C != 0) {  | 
 | 121 | + res.push_back(i-C);  | 
 | 122 | + }  | 
 | 123 | + if (i/C != R-1) {  | 
 | 124 | + res.push_back(i+C);  | 
 | 125 | + }  | 
 | 126 | + return res;  | 
 | 127 | +}  | 
 | 128 | + | 
 | 129 | +signed main() {  | 
 | 130 | + in>>R>>C;  | 
 | 131 | + grid.resize(R*C);  | 
 | 132 | + for(int i=0;i<R*C;++i){  | 
 | 133 | + in>>grid[i];  | 
 | 134 | + }  | 
 | 135 | + | 
 | 136 | + Sol allOnes;  | 
 | 137 | + for(int i=0;i<R*C;++i){  | 
 | 138 | + if(grid[i]==1){  | 
 | 139 | + for(auto neigh:neighbors(i)){  | 
 | 140 | + if(allOnes.mem[neigh].remaining==0) goto skip;  | 
 | 141 | + }  | 
 | 142 | + allOnes.mem[i].remaining=0;  | 
 | 143 | + skip:;  | 
 | 144 | + }  | 
 | 145 | + }  | 
 | 146 | + | 
 | 147 | + vector<Sol> sols(min(4*1024*1024/R/C/sizeof(UFDS), (unsigned long)1000), allOnes);  | 
 | 148 | + //sols.resize(1);  | 
 | 149 | + int bestSatisfied=0;  | 
 | 150 | + while(true){  | 
 | 151 | + int s=rand()%(sols.size());  | 
 | 152 | + Sol& sol=sols[s];  | 
 | 153 | + | 
 | 154 | + int i=rand()%(R*C);  | 
 | 155 | + if(sol.mem[i].isUsed(i)) {  | 
 | 156 | + continue;  | 
 | 157 | + }  | 
 | 158 | + | 
 | 159 | + set<int> seenr;  | 
 | 160 | + map<int,int> sizes;  | 
 | 161 | + for(auto neigh:neighbors(i)) {  | 
 | 162 | + if (sol.mem[neigh].isUsed(neigh)){  | 
 | 163 | + int nr = sol.root(neigh);  | 
 | 164 | + if (seenr.count(nr)) {  | 
 | 165 | + continue;  | 
 | 166 | + }  | 
 | 167 | + seenr.insert(nr);  | 
 | 168 | + sizes[grid[nr]] += grid[nr] - sol.mem[nr].remaining;  | 
 | 169 | + }  | 
 | 170 | + }  | 
 | 171 | + | 
 | 172 | + int bestWantedSize;  | 
 | 173 | + if (grid[i] == 0) {  | 
 | 174 | + // adding an empty cell  | 
 | 175 | + int bestDiff=numeric_limits<int>::max();  | 
 | 176 | + for(const auto& v:sizes){  | 
 | 177 | + if (v.second < v.first && v.first-v.second<bestDiff){  | 
 | 178 | + bestDiff=v.first-v.second;  | 
 | 179 | + bestWantedSize=v.first;  | 
 | 180 | + }  | 
 | 181 | + }  | 
 | 182 | + if (bestDiff==numeric_limits<int>::max()) {  | 
 | 183 | + continue;  | 
 | 184 | + }  | 
 | 185 | + } else {  | 
 | 186 | + // adding a cell with a castle  | 
 | 187 | + if(sizes[grid[i]] >= grid[i]) {  | 
 | 188 | + continue;  | 
 | 189 | + }  | 
 | 190 | + bestWantedSize=grid[i];  | 
 | 191 | + sol.mem[i].remaining=grid[i]-1;  | 
 | 192 | + }  | 
 | 193 | + | 
 | 194 | + for(auto neigh:neighbors(i)) {  | 
 | 195 | + if (sol.mem[neigh].isUsed(neigh)){  | 
 | 196 | + int nr = sol.root(neigh);  | 
 | 197 | + if(grid[nr]==bestWantedSize){  | 
 | 198 | + sol.merge(neigh,i);  | 
 | 199 | + }  | 
 | 200 | + }  | 
 | 201 | + }  | 
 | 202 | + | 
 | 203 | + //sol.debprint();  | 
 | 204 | + if (sol.satisfied > bestSatisfied) {  | 
 | 205 | + sol.print();  | 
 | 206 | + bestSatisfied = sol.satisfied;  | 
 | 207 | + }  | 
 | 208 | + }  | 
 | 209 | + | 
 | 210 | + return 0;  | 
 | 211 | +}  | 
0 commit comments