超级恶心的一个构造题…在训练的时候被折磨了两个小时,完全想偏了
首先要明确的是,只要知道了数字零的位置和矩形的长宽后,可以O(n)判断是否合法。显然我们可以暴力在sqrt(n)的时间内枚举长和宽,然后可以发现,如果有一个数字出现的次数不是4∗i,那么该数字一定是数字零的行或列坐标。再通过序列中最大数的值,即可求出行加宽的值(简单画个图就能看出来了,当然最直接的方法还是像题解那样老老实实列方程算)
剩下的难点就是计算每个数字的合法出现次数了,这里把矩形按照边分成了四段和四个顶点。每段单独考虑,这样会简单一点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>pii; typedef double db; const int maxn=1e6+5; const ll mod=998244353; const double eps=1e-10; int t,x,y,m,n; int a[maxn],cnt[maxn]; int mx,mn; int find(int i,int x,int y){ if(i<=x){ if(i<=y)return i-1; else return y-1; } else { if(i<=y)return x-1; else if(x+y-2>=i)return x+y-1-i; else return 0; } } bool check(){ if(cnt[0]!=1)return false; if(x>n||y>m)return false; for(int i=1;i<=t;i++){ int res=0; res+=find(i,x,y); res+=find(i,n-x+1,y); res+=find(i,x,m-y+1); res+=find(i,n-x+1,m-y+1); if(x>i)res++; if(y>i)res++; if(n-x+1>i)res++; if(m-y+1>i)res++; if(res!=cnt[i])return false; } return true; } bool solve(){ if(t==1&&a[t]==0){ printf("%d %d %d %d\n",1,1,1,1); return true; } for(int i=1;i*i<=t;i++){ if(t%i!=0)continue; n=i,m=t/i; y=n+m-mx-x; if(check()){ printf("%d %d %d %d\n",n,m,x,y); return true; } swap(n,m); if(check()){ printf("%d %d %d %d\n",n,m,x,y); return true; } } return false; } int main(){ int T=1; while(T--){ scanf("%d",&t); for(int i=1;i<=t;i++)scanf("%d",&a[i]); for(int i=1;i<=t;i++){ cnt[a[i]]++; mx=max(a[i],mx); } for(int i=1;i<=mx+1;i++){ if(cnt[i]!=i*4){ x=i;break; } } if(!solve())puts("-1"); }
return 0; }
|
边双模板题…求边双后找树上直径即可,这里缩点之后最好开个新图,避免错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>pii; typedef double db; const int maxn=3e5+5; const ll mod=998244353; const double eps=1e-10; int n,m; vector<int>e[maxn],g[maxn]; int fa[maxn]; int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } int dfn[maxn],low[maxn]; int idx; void tarjan(int u,int p){ dfn[u]=low[u]=++idx; for(auto v:e[u]){ if(v==p)continue; if(!dfn[v]){ tarjan(v,u); if(low[u]>low[v]){ fa[find(u)]=find(v); low[u]=min(low[u],low[v]); } } else if(dfn[v]<dfn[u]&&v!=p){ low[u]=min(low[u],dfn[v]); fa[find(u)]=find(v); } } }
int rt; int dep[maxn],mx; void dfs(int u,int p){ if(dep[u]>mx){ mx=dep[u]; rt=u; } for(auto v:g[u]){ if(v==p)continue; dep[v]=dep[u]+1; dfs(v,u); } } int main(){ int T=1; while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } for(int i=1;i<=n;i++)fa[i]=i; tarjan(1,0); for(int i=1;i<=n;i++){ int u=find(i); for(auto v:e[i]){ if(find(v)==u)continue; g[u].push_back(find(v)); } } dep[find(1)]=0; dfs(find(1),0); dep[rt]=0,mx=0; dfs(rt,0); printf("%d\n",mx); } return 0; }
|