【学习笔记】NOIP爆零赛5

poly

原题是 codechef POINPOLY

主要看到是计算几何背景就很麻。

正解考虑抽屉原理,把每个顶点的坐标按奇偶性分成四类,由抽屉原理,至少有一类会包含 n 4 \frac{n}{4} 4n个点。这些点两两配对,取中点,中点就是整点。只要这些点不是一条边的两个端点,那么终点必在多边形内。

代码非常好写。

考场上乱搞只得了 80 p t s 80pts 80pts

#include<bits/stdc++.h> #define ll long long #define db double #define pb push_back #define inf 0x3f3f3f3f3f3f3f3f #define fi first #define se second using namespace std; struct node{ int x,y; }a[100005]; map<pair<int,int>,int>id; vector<int>v[2][2]; vector<pair<int,int>>ans; int n,m; void solve(){ cin>>n;for(int i=0;i<2;i++)for(int j=0;j<2;j++)v[i][j].clear(); ans.clear(),id.clear(); for(int i=0;i<n;i++){ cin>>a[i].x>>a[i].y; v[abs(a[i].x)&1][abs(a[i].y)&1].pb(i); }m=n/10; for(int mx1=0;mx1<2;mx1++){ for(int mx2=0;mx2<2;mx2++){ for(int i=0;i<v[mx1][mx2].size();i++){ for(int j=i+1;j<v[mx1][mx2].size();j++){ int x=v[mx1][mx2][i],y=v[mx1][mx2][j]; if((x+1)%n!=y&&id.find({(a[x].x+a[y].x)/2,(a[x].y+a[y].y)/2})==id.end()){ ans.pb({(a[x].x+a[y].x)/2,(a[x].y+a[y].y)/2}); id[{(a[x].x+a[y].x)/2,(a[x].y+a[y].y)/2}]=1; if(!(--m))return; } } } } } } int main(){ ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); int T;cin>>T; while(T--){ solve(); for(auto x:ans)cout<<x.fi<<' '<<x.se<<"\n"; } }

Board Game

这题很妙啊。

应该能一眼看出 O ( n m 2 n m ) O(nm2^{nm}) O(nm2nm)的傻瓜做法,可以得到 50 p t s 50pts 50pts

正解非常脑洞:考虑将最后 5 5 5位提出来,这样恰好有 32 32 32个子集,可以用一个 unsigned int \text{unsigned int} unsigned int存下来。这很像一个 d p dp dp d p dp dp

1.1 1.1 1.1 对于高维前缀和部分,分成后 5 5 5位和前 22 22 22位的转移。设 f s f_s fs表示前 22 22 22位的二进制状态为 s s s时,后 5 5 5位所有子集的状态。先转移后 5 5 5位,类似普通高维前缀和,枚举数位 i i i以及 s ′ s' s,若 s ′ s' s的第 i i i位是 1 1 1并且 s ⊕ 2 i s\oplus 2^i s2i f s f_s fs中,那么将 s s s加入 f s f_s fs中。然后转移前 22 22 22位,枚举数位 i i i以及 s ′ s' s,若 s ′ s' s的第 i i i位是 1 1 1,那么将 f s ⊕ 2 i f_{s\oplus 2^i} fs2i中的元素全部加入 f s f_s fs中。
1.2 1.2 1.2 对于 d p dp dp部分,同样分成后 5 5 5位和前 22 22 22位。设 d p s dp_s dps表示前 22 22 22位的二进制状态为 s s s时,后 5 5 5位的 d p dp dp值为 1 1 1的子集的集合。这里值为 1 1 1表示必胜。初始高维前缀和结果为 1 1 1的状态 d p dp dp值为 0 0 0。一般的,如果能转移到一个值为 0 0 0的点那么 d p dp dp值为 1 1 1,否则 d p dp dp值为 0 0 0。倒序枚举 s s s,先做外层转移,枚举第 i i i位,若 s s s的第 i i i位是 0 0 0,将 d p s ⊕ 2 i dp_{s\oplus 2^i} dps2i中值为 0 0 0的子集全部加入 d p s dp_s dps中。然后做内层转移,具体过程类似。

这样复杂度优化成了 O ( 2 n m ) O(2^{nm}) O(2nm)。不过这样有一个 5 5 5的常数,可以再优化一下。

时限开1 s s s确实挺抽象的。而且一般的状压也不会把时限卡这么紧吧?不过鉴于出题人是个大佬嘛,嘿嘿

#include<bits/stdc++.h> using namespace std; int n,m,K,h,w,S1,S2; unsigned int v[1<<22],dp[1<<22],adj[1<<5],sub[1<<5]; string ss; int main(){ cin>>n>>m>>K;S1=1<<n*m-5,S2=1<<5; for(int i=1;i<=K;i++){ int s=0;cin>>h>>w; for(int j=0;j<h;j++){ cin>>ss; for(int k=0;k<w;k++){ if(ss[k]=='1')s+=1<<j*m+k; } } for(int j=0;j<=n-h;j++){ for(int k=0;k<=m-w;k++){ int s2=s<<j*m+k; v[s2>>5]|=1<<(s2&31); } } } for(int i=0;i<S2;i++){ for(int j=0;j<=i;j++){ if((i|j)==i)sub[i]|=1<<j; } for(int j=0;j<5;j++){ if(!(i>>j&1))adj[i]|=1<<(i|(1<<j)); } } for(int i=0;i<S1;i++){ for(int j=0;j<S2;j++){ if(v[i]&sub[j])v[i]|=1<<j; } } for(int i=0;i<n*m-5;i++){ for(int j=0;j<S1;j++){ if(j>>i&1){ v[j]|=v[j^(1<<i)]; } } } for(int i=S1-1;i>=0;i--){ for(int j=0;j<n*m-5;j++){ if(!(i>>j&1)){ dp[i]|=(-1-dp[i|(1<<j)])&(-1-v[i]); } } for(int j=S2-1;j>=0;j--){ if(((-1-v[i])>>j&1)&&(((-1-dp[i])|v[i])&(adj[j]))){ dp[i]|=1<<j; } } } cout<<((dp[0]&1)?"Alice":"Bob"); }

harmony

这题更抽象。大数据结构题你开1 s s s逗我玩呢,不过鉴于有人确实在 0.5 s 0.5s 0.5s内过了因此我也不太好说什么,况且 noi \text{noi} noi确实有过卡常数的先例,我只能说我是跑了 4 s 4s 4s的丝薄

维护方式非常脑瘫。用分块分别维护每一块内每种颜色的出现次数,然后用线段树维护可能成为答案的集合。这里我在用线段树维护时没有想到题解的做法,因此合并的复杂度可能高了些。按照题解的说法,每次重复删去 6 6 6个互不相同的数,最后剩下的本质不同的数的个数肯定不超过 6 6 6个,对这些数暴力算一下即可。

这题给我唯一的教训是,考场上不要去冲性价比很低的数据结构。因为很有可能你打完过后才发现自己的做法和正解的不一样,而你又发现怎么改都会超时。并且数据结构一写就停不下来,对其他题目的思考也有非常坏的影响,因此建议数据结构留到最后做,就算做不出来也有暴力打底 况且我是数据结构的丝薄

wait

这题应该是比较水的。当然放在 t 4 t4 t4也很抽象,其实应该多想想这道题的,况且部分分的构造也非常 trick \text{trick} trick

其实当时心态也是有一点崩吧,因为 t 2 t2 t2, t 3 t3 t3都很恶心,而 t 1 t1 t1当时也没看出来是一个比较套路的抽屉原理 真是的,每次看到这种几何题都会往计算几何方面靠,而我又完全不会

真的很膜拜 x f xf xf的心态啊。。。

首先考虑离散化。对于 w i = − 1 w_i=-1 wi=1的点,如果我们把 [ l , r ) [l,r) [l,r)看成 l l l r r r的一条边,然后将其定向,把度为奇数的点连起来再跑欧拉回路,这样我们发现每个点恰好被覆盖的黑白区间数目相等,去掉加的那些虚边后显然还是合法的。这样就有 45 p t s 45pts 45pts

对于一般的情况,我们还是先加虚边,再钦定每一条边的方向,最后跑网络流即可。

把网络流板题放 t 4 t4 t4,真是抽象


__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530027.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
历史上的今天:
2022-02-22 【题解】加权约数和
点击右上角即可分享
微信分享提示