zoukankan      html  css  js  c++  java
  • 【LOJ#3197】【eJOI2019】—T 形覆盖(并查集)

    传送门

    考虑2个关键点之间的关系

    如果挨在一起,那么周围选的6个是确定的

    如果角挨在一起,那么周围选的6个也是确定的

    如果隔了一个格子,那么就是在周围7个里面去掉最小的一个

    维护相关联的一堆关键点
    看周围能填的格子数是否足够

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=(1<<20)|5;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #define pb push_back
    #define re register
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define cs const
    #define bg begin
    #define ll long long
    inline ll readl(){
    	char ch=gc();
    	ll res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int mod=1e9+7;
    inline int add(int a,int b){a+=b-mod;return a+(a>>31&mod);}
    inline void Add(int &a,int b){a+=b-mod;a+=a>>31&mod;}
    inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
    inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    inline void Mul(int &a,int b){a=1ll*a*b%mod;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    cs int N=2000005;
    int m,n,q;
    int pos(int x,int y){
    	return x*n+y;
    }
    int vis[N];
    int a[N],sum,fa[N],tot,ans;
    struct pt{
    	int x,y;
    }p[N];
    vector<int> S[N];
    cs int tx[5]={0,1,0,-1,0};
    cs int ty[5]={-1,0,1,0,0};
    int find(int x){
    	return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    inline void merge(int u,int v){
    	int f1=find(u),f2=find(v);
    	if(f1!=f2)fa[f1]=f2;
    }
    int main(){
    	#ifdef Stargazer
    	freopen("lx.cpp","r",stdin);
    	#else
    	#ifndef ONLINE_JUDGE
    	#endif
    	#endif
    	m=read(),n=read();
    	tot=n*m;
    	for(int i=0;i<m;i++)
    	for(int j=0;j<n;j++){
    		int x=read();
    		a[pos(i,j)]=x;
    	}
    	q=read();
    	for(int i=1;i<=q;i++)fa[i]=i;
    	for(int i=1;i<=q;i++){
    		int x=read(),y=read(),px,py;
    		p[i].x=x,p[i].y=y;
    		for(int t=0;t<=4;t++){
    			px=x+tx[t],py=y+ty[t];
    			if(!(0<=px&&px<m&&0<=py&&py<n))continue;
    			if(vis[pos(px,py)])merge(i,vis[pos(px,py)]);
    			vis[pos(px,py)]=i;
    		}
    	}
    	for(int i=1;i<=q;i++){
    		S[find(i)].pb(i);
    	}
    	memset(vis,0,sizeof(vis));
    	for(int i=1;i<=q;i++)if(S[i].size()){
    		int siz=0,mn=1e9,s=0;
    		for(int &t:S[i]){
    			vis[pos(p[t].x,p[t].y)]=1,s+=a[pos(p[t].x,p[t].y)];
    		}
    		for(int &t:S[i]){
    			int x=p[t].x,y=p[t].y,px,py;
    			for(int tt=0;tt<=3;tt++){
    				px=x+tx[tt],py=y+ty[tt];
    				if(!(0<=px&&px<m&&0<=py&&py<n))continue;
    				if(vis[pos(px,py)])continue;
    				vis[pos(px,py)]=1,s+=a[pos(px,py)],siz++,chemn(mn,a[pos(px,py)]);
    			}
    		}
    		if(siz<S[i].size()*3){puts("No");return 0;}
    		if(siz==S[i].size()*3)ans+=s;
    		if(siz>S[i].size()*3)ans+=s-mn;
    	}
    	cout<<ans;
    }
    
  • 相关阅读:
    'IDataObject': ambiguous symbol的解决方法
    捕获windows系统的sleep或hibernate状态
    CallingConvention理解
    Exception from HRESULT: 0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL))
    .Net Managed C++如何获取当前线程id和当前进程id
    div垂直居中于div中
    父级是relative,子级为absolute的情况下,子级宽度自适应
    background-img高度固定,图片自适应
    如何让两个input紧挨着.
    C# 调用百度短链接api
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328391.html
Copyright © 2011-2022 走看看