zoukankan      html  css  js  c++  java
  • JZOJ 2020.07.30【NOIP提高组】模拟

    总结

    本场比赛很不负责对待
    暴力都没怎么打
    一个半小时后才开始打题
    很悲剧的只有 (23+11+36=70)

    (T1) 4300. 装饰大楼

    题目

    思路

    很无聊的找规律题
    考场弃疗

    (Code)

    #include<cstdio>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    
    const int N = 1e6 + 5;
    int n , a[N] , s , x , t;
    LL ans;
    
    int main()
    {
    	freopen("building.in" , "r" , stdin);
    	freopen("building.out" , "w" , stdout);
    	scanf("%d" , &n);
    	for(register int i = 1; i < n; i++) scanf("%d" , &a[i]);
    	for(register int i = 1; i < n; i++)
    	{
    		ans += (LL)s + 1;
    		if (a[i] <= s + 1) ans--;
    		s = max(s , a[i]);
    	}
    	ans += (LL)s + 1;
    	s = 0;
    	for(register int i = 1; i < n; i++)
    	{
    		if (a[i] - x > 2)
    		{
    			printf("0");
    			return 0;
    		}
    		else if (a[i] - x == 2) 
    		{
    			s++;
    			if (s == 1) t = i;
    		}
    		if (s >= 2)
    		{
    			printf("0");
    			return 0;
    		}
    		x = max(x , a[i]);
    	}
    	if (s == 1)
    	{
    		x = s = 0;
    		for(register int i = 1; i < t; i++)
    			if (a[i] > x) x = a[i] , s = i;
    		ans = t - s;
    	}
    	printf("%lld" , ans);
    }
    

    (T2) 4301. 备用钥匙

    题目

    思路

    奇怪的 (dp)
    很容易想到按时间排序
    相邻两个时间分离开和回来四种情况讨论
    不用钥匙的直接加,记到 (ans)
    单独用一个钥匙的另开数组记需要钥匙者产生的贡献,记到 (c)
    两个都需要就弄出链来并算给他们两把钥匙能获得的贡献,记到 (se)

    然后调整 (dp) 的顺序
    链上的连在一起
    (f_{i,j}) 表示前 (1..i) 中选 (j) 个人且强行让 (i) 也持有钥匙的最大答案, (g_{i,j}=max_{k=1}^{i} f_{k,j})
    那么转移:(f_{i,j}=max{f_{i-1,j-1}+se[i],g[i-2][j-1]}+c[i])
    最终 (ans=ans+g[n][k])

    (Code)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int N = 2005;
    int n , m , k , tot , s[N] , se[N] , sz[N] , c[N] , ans , pre[N] , nxt[N] , f[N][N] , g[N][N] , vis[N] , b[N];
    
    struct node{
    	int id , t , s;
    }a[2 * N];
    
    inline bool cmp(node x , node y){return x.t < y.t;}
    
    int main()
    {
    	freopen("key.in" , "r" , stdin);
    	freopen("key.out" , "w" , stdout);
    	scanf("%d%d%d" , &n , &m , &k);
    	int p , q;
    	for(register int i = 1; i <= n; i++)
    	{
    		scanf("%d%d" , &p , &q);
    		a[++tot].id = i , a[tot].t = p , a[tot].s = 1;
    		a[++tot].id = i , a[tot].t = q , a[tot].s = 2;
    	}
    	sort(a + 1 , a + tot + 1 , cmp);
    	ans = a[1].t + m - a[tot].t;	
    	
    	for(register int i = 1; i <= tot; i++)
    	{
    		if (a[i].s == 2 && a[i + 1].s == 1) ans += a[i + 1].t - a[i].t;
    		if (a[i].id == a[i + 1].id) s[a[i].id] += a[i + 1].t - a[i].t;
    		else if (a[i].s == 1 && a[i + 1].s == 1) s[a[i].id] += a[i + 1].t - a[i].t;
    		else if (a[i].s == 2 && a[i - 1].s == 2) s[a[i].id] += a[i].t - a[i - 1].t;
    		else if (a[i].s == 1 && a[i + 1].s == 2)
    		{
    			pre[a[i + 1].id] = a[i].id;
    			nxt[a[i].id] = a[i + 1].id;
    			sz[a[i + 1].id] = a[i + 1].t - a[i].t;
    		}
    	}
    	
    	int to;
    	tot = 0;
    	for(register int i = 1; i <= n; i++)
    	if (!vis[i])
    	{
    		to = i;
    		while (pre[to]) to = pre[to];
    		while (to) b[++tot] = to , vis[to] = 1 , to = nxt[to];
    	}
    	
    	for(register int i = 1; i <= n; i++) c[i] = s[b[i]] , se[i] = sz[b[i]];
    	f[1][1] = g[1][1] = c[1];
    	for(register int i = 2; i <= n; i++)
    	{
    		g[i][1] = max(g[i - 1][1] , f[i][1] = c[i]);
    		for(register int j = 2; j <= k; j++)
    			g[i][j] = max(g[i - 1][j] , f[i][j] = max(f[i - 1][j - 1] + se[i] , g[i - 2][j - 1]) + c[i]);
    	}
    	
    	printf("%d" , ans + g[n][k]);
    }
    

    (T3) 4302. IOIOI卡片占卜

    题目

    思路

    牛逼得不得了的操作:记给定的序列 (I)(1)(O)(0)。让这个序列相邻两个异或
    于是区间 ([l..r]) 翻转变为异或单点 (l-1)(r) (亲手模拟看看)
    异或后的序列只剩 (4)(1),让这四个 (1)(0) 的最少代价即为答案
    那么我们把 (l-1)(r) 连边,边权为 (r-l+1),表示 (l-1)(r) 的最小代价为 (r-l+1)
    因为一次翻一个区间,即转化后的一次翻两个点,所以现在要使 (4)(1) 配对
    使他们最短路的和最小即为答案

    (Code)

    #include<cstdio>
    #include<queue>
    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    
    const int N = 5e5 + 5;
    int a , b , c , d , e , vis[N] , h[N] , tot , n;
    LL dis[N] , ans;
    
    struct edge{
    	int nxt , to , w;
    }E[2 * N];
    
    struct node{
    	int id;
    	LL d;
    	bool operator < (node c) const
    	{
    		return d > c.d;
    	}
    };
    
    inline void add(int x , int y , int z)
    {
    	E[++tot].to = y;
    	E[tot].w = z;
    	E[tot].nxt = h[x];
    	h[x] = tot;
    }
    
    priority_queue<node> Q;
    
    inline LL dij(int s , int t)
    {
    	memset(vis , 0 , sizeof vis);
    	memset(dis , 60 , sizeof dis);
    	while (!Q.empty()) Q.pop();
    	dis[s] = 0;
    	Q.push((node){s , dis[s]});
    	node x;
    	while (!Q.empty())
    	{
    		x = Q.top();
    		Q.pop();
    		if (vis[x.id]) continue;
    		vis[x.id] = 1;
    		if (x.id == t) break;
    		for(register int i = h[x.id]; i; i = E[i].nxt)
    		{
    			int v = E[i].to;
    			if (dis[x.id] + E[i].w < dis[v])
    			{
    				dis[v] = dis[x.id] + E[i].w;
    				Q.push((node){v , dis[v]});
    			}
    		}
    	}
    	return dis[t];
    }
    
    int main()
    {
    	freopen("card.in" , "r" , stdin);
    	freopen("card.out" , "w" , stdout);
    	scanf("%d%d%d%d%d" , &a , &b , &c , &d , &e);
    	scanf("%d" , &n);
    	int l , r;
    	for(register int i = 1; i <= n; i++)
    	{
    		scanf("%d%d" , &l , &r);
    		l--;
    		add(l , r , r - l) , add(r , l , r - l);
    	}
    	ans = min(dij(a , a + b) + dij(a + b + c , a + b + c + d) , dij(a , a + b + c) + dij(a + b , a + b + c + d));
    	ans = min(ans , dij(a , a + b + c + d) + dij(a + b , a + b + c));
    	if (ans >= 4340410370284600380) printf("-1");
    	else printf("%lld" , ans);
    }
    
  • 相关阅读:
    ios9 键盘使uiwindow上移
    UIStackView在UITableviewCell中
    uitableviewcell侧滑删除等
    系统设置
    UIImagePickerController 导航样式调整
    设置frame时,大小在不同型号手机上不同
    storyBoard Reference 的坑
    uitableview 滚回顶部
    swift格式化输出
    UIAlertController
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13405935.html
Copyright © 2011-2022 走看看