【学习笔记】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 
       
      
    s⊕2i在 
     
      
       
        
        
          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} 
       
      
    fs⊕2i中的元素全部加入 
     
      
       
        
        
          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} 
       
      
    dps⊕2i中值为 
     
      
       
       
         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,真是抽象

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号