QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#791579#6746. Merge the RectanglesHJR#TL 79ms135200kbC++176.5kb2024-11-28 19:39:462024-11-28 19:39:47

Judging History

你现在查看的是最新测评结果

  • [2024-11-28 19:39:47]
  • 评测
  • 测评结果:TL
  • 用时:79ms
  • 内存:135200kb
  • [2024-11-28 19:39:46]
  • 提交

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...

output:


result: