2023/2/22 模拟赛
本场题目确实逆天,前三题赛时无人切,最高分不过一百左右。仍然是一如既往的菜,又爆零了,什么时候才能走出这个圈啊……
\(T1:Polygon\)
考场上一眼计算几何,直接毙掉不做。考完后发现很简单……
正解方法确实抽象……首先,把输入的整点分为 \((奇,奇)\),\((奇,偶)\),\((偶,偶)\),\((偶,奇)\),这四种类型的点。考虑到只需输出 \(\lfloor \frac{n}{10}\rfloor\),个点,相对来说不多。又因为是凸多边形,因此考虑按照点两个坐标的奇偶性配对,使得两点的中点为整点,输出即可。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 1e6;
int n,T;
vector<pair<int,pair<int,int> > > ty1,ty2,ty3,ty4;
map<pair<int,int>,bool> m;
signed main(){
scanf("%lld",&T);
while(T--){
ty1.clear(),ty2.clear(),ty3.clear(),ty4.clear();
bool flag = 0;
scanf("%lld",&n);
for(int i = 1; i <= n; i++){
int u,v;
scanf("%lld%lld",&u,&v);
if(abs(u) % 2 == 1){
if(abs(v) % 2 == 1)ty1.push_back(make_pair(i,make_pair(u,v)));
else ty2.push_back(make_pair(i,make_pair(u,v)));
}
else{
if(abs(v) % 2 == 1)ty3.push_back(make_pair(i,make_pair(u,v)));
else ty4.push_back(make_pair(i,make_pair(u,v)));
}
}
int cnt = 0;
for(int i = 0; i < ty1.size(); i++){
int x1 = ty1[i].second.first,y1 = ty1[i].second.second;
for(int j = i + 1; j < ty1.size(); j++){
int x2 = ty1[j].second.first,y2 = ty1[j].second.second;
if(abs(ty1[i].first - ty1[j].first) == 1)continue;
int x3 = (x1 + x2) / 2,y3 = (y1 + y2) / 2;
if(m.find(make_pair(x3,y3)) != m.end())continue;
m[make_pair(x3,y3)] = 1;
printf("%lld %lld\n",x3,y3);
++cnt;
if(cnt == n / 10){
flag = 1;
break;
}
}
if(flag)break;
}
if(flag)continue;
for(int i = 0; i < ty2.size(); i++){
int x1 = ty2[i].second.first,y1 = ty2[i].second.second;
for(int j = i + 1; j < ty2.size(); j++){
int x2 = ty2[j].second.first,y2 = ty2[j].second.second;
if(abs(ty2[i].first - ty2[j].first) == 1)continue;
int x3 = (x1 + x2) / 2,y3 = (y1 + y2) / 2;
if(m.find(make_pair(x3,y3)) != m.end())continue;
m[make_pair(x3,y3)] = 1;
printf("%lld %lld\n",x3,y3);
++cnt;
if(cnt == n / 10){
flag = 1;
break;
}
}
if(flag)break;
}
if(flag)continue;
for(int i = 0; i < ty3.size(); i++){
int x1 = ty3[i].second.first,y1 = ty3[i].second.second;
for(int j = i + 1; j < ty3.size(); j++){
int x2 = ty3[j].second.first,y2 = ty3[j].second.second;
if(abs(ty3[i].first - ty3[j].first) == 1)continue;
int x3 = (x1 + x2) / 2,y3 = (y1 + y2) / 2;
if(m.find(make_pair(x3,y3)) != m.end())continue;
m[make_pair(x3,y3)] = 1;
printf("%lld %lld\n",x3,y3);
++cnt;
if(cnt == n / 10){
flag = 1;
break;
}
}
if(flag)break;
}
if(flag)continue;
for(int i = 0; i < ty4.size(); i++){
int x1 = ty4[i].second.first,y1 = ty4[i].second.second;
for(int j = i + 1; j < ty4.size(); j++){
int x2 = ty4[j].second.first,y2 = ty4[j].second.second;
if(abs(ty4[i].first - ty4[j].first) == 1)continue;
int x3 = (x1 + x2) / 2,y3 = (y1 + y2) / 2;
if(m.find(make_pair(x3,y3)) != m.end())continue;
m[make_pair(x3,y3)] = 1;
printf("%lld %lld\n",x3,y3);
++cnt;
if(cnt == n / 10){
flag = 1;
break;
}
}
if(flag)break;
}
}
}
//1
//11
//0 0
//1 1
//2 3
//2 5
//0 10
//-2 10
//-5 9
//-8 7
//-8 4
//-6 1
//-2 0
\(T2\)
期望 \(DP\)……纯纯不会。
题解先放这,看看以后能不能看懂。
\(T3:\)
这个数据结构……过于逆天,还是放个题解先,看以后能不能懂。
\(T4:等你哈苏德\)
这个题考的主要是混合图欧拉回路的应用,关于混合图欧拉回路,可以参见这个。接下来讨论下这个题为什么是混合图欧拉回路的做法。
首先将题目抽象一下:如果一个 \([l,r]\) 的区间是黑色,就看作从 \(l\) 向 \(r + 1\) 连了一条边,否则就是从 \(r + 1\) 向 \(l\) 连一条边。如此,一个点被连入一条边,度加 \(1\),就相当于被黑色覆盖了,如果从它这里出了一条边,度减 \(1\),就相当于被白色覆盖了一次。如此,便将颜色的覆盖转化为了点的出入度之差。当每个点被白色覆盖的次数与被黑色覆盖的次数相等时,等价于图中有一条串了所有点的欧拉回路。
然而我们随意定向的边,可能导致有些点的出入度之差为奇数,我们将这些度数为奇数的点存到 \(a\),排序后将 \(a_i\) 与 \(a_{i + 1}\) 相连。这可以满足一个区间内的黑白覆盖次数绝对值之差小于等于 \(1\),最后跑混合图欧拉回路即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6;
const int INF = 0x3f3f3f3f;
int id[MAXN + 5],n,m,tot,deg[MAXN + 5],node[MAXN + 5],cno,head[MAXN + 5],s,t,dis[MAXN + 5],cur[MAXN + 5],ans[MAXN + 5],cnt;
bool vis[MAXN + 5];
vector<int> lsh;
struct E{
int l,r,w;
}e[MAXN + 5];
struct EDGE{
int u,v,w,next;
}edge[MAXN + 5];
void ADD(int u,int v,int w){
++tot;
edge[tot].u = u;
edge[tot].v = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot;
}
void add(int u,int v,int w){
ADD(u,v,w);
ADD(v,u,0);
}
bool bfs(){
queue<int> q;
q.push(s);
memset(dis,0,sizeof dis);
dis[s] = 1;
while(!q.empty()){
int u = q.front();
q.pop();
for(int i = head[u]; i; i = edge[i].next){
int v = edge[i].v;
if(!dis[v] && edge[i].w > 0){
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
if(dis[t])return 1;
return 0;
}
int dfs(int u,int dist){
if(u == t)return dist;
for(int &i = cur[u]; i; i = edge[i].next){
int v = edge[i].v;
if(dis[v] == dis[u] + 1 && edge[i].w > 0){
int di = dfs(v,min(edge[i].w,dist));
if(di > 0){
edge[i].w -= di;
edge[i ^ 1].w += di;
return di;
}
}
}
return 0;
}
int dinic(){
int an = 0;
while(bfs()){
for(int i = s; i <= t; i++){cur[i] = head[i];}
while(int di = dfs(s,INF))an += di;
}
return an;
}
int main(){
freopen("wait.in","r",stdin);
freopen("wait.out","w",stdout);
tot = 1;
scanf("%d%d",&m,&n);
for(int i = 1; i <= m; i++){
scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].w);
e[i].r++;
lsh.push_back(e[i].l);
lsh.push_back(e[i].r);
}
sort(lsh.begin(),lsh.end());
lsh.erase(unique(lsh.begin(),lsh.end()),lsh.end());
for(int i = 1; i <= m; i++){
e[i].l = lower_bound(lsh.begin(),lsh.end(),e[i].l) - lsh.begin() + 1;
e[i].r = lower_bound(lsh.begin(),lsh.end(),e[i].r) - lsh.begin() + 1;
}
for(int i = 1; i <= m; i++){
if(e[i].w == -1){
add(e[i].l,e[i].r,1);
ans[tot / 2] = 1;
deg[e[i].l]++;
deg[e[i].r]--;
id[i] = tot;
}
else if(e[i].w == 1)deg[e[i].l]++,deg[e[i].r]--;
else deg[e[i].r]++,deg[e[i].l]--;
node[++cno] = e[i].l,node[++cno] = e[i].r;
}
sort(node + 1,node + 1 + cno);
for(int i = 1; i < cno; i += 2){
if(node[i] == node[i + 1])continue;
++deg[node[i]],--deg[node[i + 1]];
add(node[i],node[i + 1],1);
}
s = 0,t = lsh.size() + 1;
for(int i = 1; i <= lsh.size(); i++){
if(deg[i] >= 0){
add(s,i,deg[i] / 2);
cnt += deg[i] / 2;
}
else{
add(i,t,(-deg[i] / 2));
}
}
int k;
k = dinic();
if(k < cnt){
cout << "-1";
return 0;
}
for(int i = 1; i <= m; i++){
if(e[i].w == -1){
cout << (edge[id[i]].w ^ 1) << " ";
}
else cout << e[i].w << " ";
}
}
//4 1000000000
//1 9 -1
//2 6 -1
//1 8 -1
//1 7 -1