QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#791579 | #6746. Merge the Rectangles | HJR# | TL | 79ms | 135200kb | C++17 | 6.5kb | 2024-11-28 19:39:46 | 2024-11-28 19:39:47 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define debug(x) cout<<#x<<": "<<x<<endl
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
using ll=long long;
using ull=unsigned long long;
const int N=2*2250000;
// int del[N];
// struct rec
// {
// array<int,4> node;
// };
// int f[N];
// int leader(int x){
// while(x!=f[x])
// x=f[x]=f[f[x]];
// return x;
// }
// void merge(int x,int y){
// x=leader(x);
// y=leader(y);
// if(x==y)
// return;
// f[y]=x;
// }
unordered_map<ull,vector<int>> mp;
unordered_map<ull,int> del;
ull tran(int x,int y){
if(x>y)
swap(x,y);
return 1ull*x*10000000+y;
}
struct node
{
ull id;
vector<int> cmp;
bool operator<(const node&t)const{
return cmp.size()<t.cmp.size();
}
};
int d[5][2]={{0,1},{1,0},{0,-1},{-1,0},{0,1}};
void solve(){
int n,m;
cin>>n>>m;
vector<vector<int>> id(n+1,vector<int>(m+1));
vector<vector<int>> adj((n+1)*(m+1)+1,vector<int>(4));
int tim=0;
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
id[i][j]=++tim;
}
}
for(int i=0,ci=1;i<n-1;i++,ci++){
string s;
cin>>s;
int cj=0;
for(auto x:s){
if(x=='1'){
adj[id[ci][cj]][1]=2;
adj[id[ci][cj+1]][3]=2;
}
cj++;
}
}
for(int i=0,ci=0;i<n;i++,ci++){
string s;
cin>>s;
int cj=1;
for(auto x:s){
if(x=='1'){
adj[id[ci][cj]][2]=2;
adj[id[ci+1][cj]][0]=2;
}
cj++;
}
}
for(int ci=0;ci<n;ci++){
adj[id[ci][0]][2]=1;
adj[id[ci+1][0]][0]=1;
adj[id[ci][m]][2]=1;
adj[id[ci+1][m]][0]=1;
}
for(int cj=0;cj<m;cj++){
adj[id[0][cj]][1]=1;
adj[id[0][cj+1]][3]=1;
adj[id[n][cj]][1]=1;
adj[id[n][cj+1]][3]=1;
}
int ctim=0;
vector<array<int,4>> allrec;
vector<array<ull,4>> rechs;
auto dl=[&](int ci,int cj,int dir)->void{
if(dir==0){
adj[id[ci][cj]][0]--;
adj[id[ci-1][cj]][2]--;
}
else if(dir==1){
adj[id[ci][cj]][1]--;
adj[id[ci][cj+1]][3]--;
}
else if(dir==2){
adj[id[ci][cj]][2]--;
adj[id[ci+1][cj]][0]--;
}
else{
adj[id[ci][cj]][3]--;
adj[id[ci][cj-1]][1]--;
}
};
priority_queue<node> q;
vector<ull> edg;
auto dfs=[&](int i,int j)->void{
array<int,4> now;
now[0]=id[i][j];
int flag=1;
adj[id[i][j]][1]--;
adj[id[i][j+1]][3]--;
int ci=i,cj=j+1;
while(1){
if(flag&&adj[id[ci][cj]][(flag+1)%4]){
dl(ci,cj,(flag+1)%4);
now[flag]=id[ci][cj];
ci+=d[flag][0],cj+=d[flag][1];
flag++;
if(flag==4)
flag=0;
}
else{
dl(ci,cj,flag);
if(flag)
ci+=d[flag-1][0],cj+=d[flag-1][1];
else
ci+=d[3][0],cj+=d[3][1];
}
if(ci==i&&cj==j){
break;
}
}
allrec.push_back(now);
rechs.push_back({});
for(int i=0;i<4;i++){
ull cur=tran(now[i],now[(i+1)%4]);
rechs[ctim][i]=cur;
edg.push_back(cur);
mp[cur].push_back(ctim);
}
ctim++;
};
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(adj[id[i][j]][1]>0){
dfs(i,j);
}
}
}
sort(edg.begin(),edg.end());
edg.erase(unique(edg.begin(),edg.end()),edg.end());
for(auto x:edg){
// debug(x);
// debug(mp[x].size());
q.push({x,mp[x]});
}
auto mergerec=[&](int x,int y,ull cur)->void{
for(int i=0;i<4;i++){
mp[rechs[x][i]].erase(find(mp[rechs[x][i]].begin(),mp[rechs[x][i]].end(),x));
mp[rechs[y][i]].erase(find(mp[rechs[y][i]].begin(),mp[rechs[y][i]].end(),y));
}
array<int,4> now;
for(int i=0;i<4;i++){
if(rechs[x][i]==cur){
if(i==0){
now[0]=allrec[y][0];
now[1]=allrec[y][1];
now[2]=allrec[x][2];
now[3]=allrec[x][3];
}
else if(i==1){
now[0]=allrec[x][0];
now[1]=allrec[y][1];
now[2]=allrec[y][2];
now[3]=allrec[x][3];
}
else if(i==2){
now[0]=allrec[x][0];
now[1]=allrec[x][1];
now[2]=allrec[y][2];
now[3]=allrec[y][3];
}
else{
now[0]=allrec[y][0];
now[1]=allrec[x][1];
now[2]=allrec[x][2];
now[3]=allrec[y][3];
}
}
}
del[cur]=1;
allrec.push_back(now);
rechs.push_back({});
for(int i=0;i<4;i++){
ull cur=tran(now[i],now[(i+1)%4]);
rechs[ctim][i]=cur;
edg.push_back(cur);
mp[cur].push_back(ctim);
q.push({cur,mp[cur]});
}
ctim++;
};
set<ull> yes;
yes.insert(tran(id[0][0],id[0][m]));
yes.insert(tran(id[0][m],id[n][m]));
yes.insert(tran(id[n][m],id[n][0]));
yes.insert(tran(id[n][0],id[0][0]));
while(!q.empty()){
ull cur=q.top().id;
vector<int> now=q.top().cmp;
q.pop();
int ok=1;
if(now!=mp[cur])
continue;
if(del[cur])
continue;
if(yes.count(cur)||mp[cur].size()==0)
continue;
if(mp[cur].size()<2){
cout<<"NO"<<endl;
return;
}
else{
mergerec(mp[cur][0],mp[cur][1],cur);
}
}
cout<<"YES"<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
int t=1;
while(t--){
solve();
}
}
/*
贡献法
正难则反
数小状压
关系连边
拆位
广义单调性
最长转最短
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3708kb
input:
3 4 0000 0111 101 101 110
output:
YES
result:
ok answer is YES
Test #2:
score: 0
Accepted
time: 0ms
memory: 3580kb
input:
3 3 110 011 01 11 10
output:
NO
result:
ok answer is NO
Test #3:
score: 0
Accepted
time: 79ms
memory: 135200kb
input:
1500 1500 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
output:
YES
result:
ok answer is YES
Test #4:
score: -100
Time Limit Exceeded
input:
1500 1500 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111...