首页 > 其他分享 >2023省选武汉联测13

2023省选武汉联测13

时间:2023-04-20 21:12:47浏览次数:44  
标签:pre 13 Min 省选 Max int 联测 include color

T1 构树

直接 \(O(n^2)\) 暴力枚举连边即可。

code

#include <cstdio>
#include <vector>
#include <set>
#include <utility>
using namespace std;
const int max1 = 1000;
int n, Min[max1 + 5], Max[max1 + 5];
vector <int> part[max1 + 5];
int color[max1 + 5];
set < pair <int, int> > edge;
int main ()
{
    freopen("tree.in", "r", stdin);
    freopen("tree.out", "w", stdout);
    scanf("%d", &n);
    for ( int i = 1; i <= n; i ++ )
        scanf("%d%d", &Min[i], &Max[i]);
    bool illegal = false;
    for ( int i = 1; i <= n; i ++ )
    {
        int v = Min[i];
        if ( i < Min[v] || i > Max[v] )
            { illegal = true; break; }
        v = Max[i];
        if ( i < Min[v] || i > Max[v] )
            { illegal = true; break; }
    }
    if ( illegal )
        { printf("-1\n"); return 0; }
    for ( int i = 1; i <= n; i ++ )
        part[i].push_back(i), color[i] = i;
    for ( int i = 1; i <= n; i ++ )
    {
        int u = i, v = Min[i];
        if ( u > v )
            swap(u, v);
        if ( u == v )
            { illegal = true; break; }
        if ( edge.find(make_pair(u, v)) == edge.end() )
        {
            if ( color[u] == color[v] )
                { illegal = true; break; }
            edge.insert(make_pair(u, v));
            int id = color[v];
            for ( auto p : part[id] )
            {
                color[p] = color[u];
                part[color[u]].push_back(p);
            }
            part[id].clear();
        }
        u = i, v = Max[i];
        if ( u > v )
            swap(u, v);
        if ( u == v )
            { illegal = true; break; }
        if ( edge.find(make_pair(u, v)) == edge.end() )
        {
            if ( color[u] == color[v] )
                { illegal = true; break; }
            edge.insert(make_pair(u, v));
            int id = color[v];
            for ( auto p : part[id] )
            {
                color[p] = color[u];
                part[color[u]].push_back(p);
            }
            part[id].clear();
        }
    }
    if ( illegal )
        { printf("-1\n"); return 0; }
    for ( int i = 1; i <= n; i ++ )
    {
        for ( int j = i + 1; j <= n; j ++ )
        {
            if ( color[i] == color[j] )
                continue;
            if ( i >= Min[j] && i <= Max[j] && j >= Min[i] && j <= Max[i] )
            {
                edge.insert(make_pair(i, j));
                int id = color[j];
                for ( auto p : part[id] )
                {
                    color[p] = color[i];
                    part[color[i]].push_back(p);
                }
                part[id].clear();
            }
        }
    }
    if ( (int) edge.size() != n - 1 )
        printf("-1\n");
    else
        for ( auto v : edge )
            printf("%d %d\n", v.first, v.second);
    return 0;
}

T2 交互

考虑按照中序遍历的顺序求解树的结构,方便起见我们将整棵平衡树定义为 \(0\) 节点的右儿子,记录 \(pre_u\) 表示 \(u\) 节点所在左链的顶部的父亲,按照顺序依次枚举每个节点 \(u\) ,考虑 \(u+1\) 相对于 \(u\) 的位置,如果 \(u+1\) 位于 \(u\) 的子树内,显然 \(u+1\) 为 \(u\) 的右子树内最靠左的点,那么 \(pre_{u+1}=u\) ,继续枚举 \(u\) 求解,如果 \(u+1\) 不在 \(u\) 的子树内,容易发现 \(u\) 和 \(u+1\) 一定存在祖先关系,设 \(p=u\) ,判断 \(u+1\) 是否位于 \(pre_p\) 的子树内,如果位于 \(pre_p\) 的子树内,显然 \(u+1\) 是 \(p\) 的父亲, \(pre_{u+1}=pre_p\) ,否则 \(pre_p\) 是 \(p\) 的父亲,令 \(pre_p\to p\), 继续判断。

code

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include "interact.h"
using namespace std;
const int max1 = 100;
int lim, pre[max1 + 5], Min[max1 + 5], Max[max1 + 5];
bool Query ( int u, int l, int r )
{
	if ( !u )
	{
		if ( l == 0 && r == lim )
			return true;
		return false;
	}
	return query(u, l, r);
}
void Report ( int u, int v )
{
	if ( u )
	{
		report(u, v);
		Min[u] = min(Min[u], Min[v]);
		Max[u] = max(Max[u], Max[v]);
	}
	return;
}
void Solve ( int L )
{
	if ( !Query(L, Min[L], Max[L]) )
	{
		pre[L + 1] = L;
		Solve(L + 1);
	}
	else
	{
		int p = L;
		while ( p )
		{
			if ( !Query(pre[p], Min[pre[p]], Max[p]) )
			{
				Report(L + 1, p);
				pre[L + 1] = pre[p];
				Solve(L + 1);
				break;
			}
			else
			{
				Report(pre[p], p);
				p = pre[p];
			}
		}
	}
	return;
}
void guess ( int n )
{
	lim = n;
	Min[0] = 0, Max[0] = n;
	for ( int i = 1; i <= n; i ++ )
		pre[i] = 0, Min[i] = Max[i] = i;
	pre[1] = 0;
	Solve(1);
	return;	
}

T3 构图

容易发现每个点的度数只有 \(k\) 和 \(k+1\) 两种可能,因此枚举度数为 \(k\) 的点的个数,找到边数最小的方案,贪心的连边即可。

code

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int max1 = 1000;
const int inf = 0x3f3f3f3f;
int n, k;
struct Point
{
    int x, d;
    Point () {}
    Point ( int __x, int __d )
        { x = __x, d = __d; }
    bool operator < ( const Point &A ) const
        { return d < A.d; }
};
queue <Point> que;
void Solve ( int cnt )
{
    for ( int i = cnt + 1; i <= n; i ++ )
        que.push(Point(i, k + 1));
    for ( int i = 1; i <= cnt; i ++ )
    {
        for ( int j = 1; j <= k; j ++ )
        {
            Point now = que.front();
            que.pop();
            printf("%d %d\n", i, now.x);
            --now.d;
            que.push(now);
        }
    }
    while ( que.front().d > 0 )
    {
        Point now = que.front();
        que.pop();
        while ( now.d > 0 )
        {
            --now.d;
            Point tmp = que.front();
            que.pop();
            printf("%d %d\n", now.x, tmp.x);
            --tmp.d;
            que.push(tmp);
        }
    }
    return;
}
int main ()
{
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);
    int Min = inf, cnt = 0;
    scanf("%d%d", &n, &k);
    for ( int i = 1; i + k <= n; i ++ )
    {
        int up = i * k + ( max(0, ( n - i ) * ( k + 1 ) - i * k) + 1 >> 1 );
        if ( up < Min )
            Min = up, cnt = i;
    }
    printf("%d\n", Min);
    Solve(cnt);
    return 0;
}

标签:pre,13,Min,省选,Max,int,联测,include,color
From: https://www.cnblogs.com/KafuuChinocpp/p/17338348.html

相关文章

  • # 2023省选武汉联测12
    T1图案首先是题解做法:考虑对于每个\(r\),判断\(s[1,r]\)是否为一个图案,设\(r=ik+j\),其中\(0\lej\lei\),如果存在一组这样的\((i,j)\)满足\(s[1,r-i]=s[i+1,r]\),那么\(s[1,r]\)是一个图案,考虑这样做的正确性,如果\(s[1,r-i]=s[i+1,r]\),那么一定有\(s[i+1,r-2i]=s......
  • 2023省选武汉联测11
    T1游戏对于树上三点\((u,v,w)\),一定存在一个点\(p\)满足\(p\tou\)与\(p\tov\)与\(p\tow\)的路径两两不重合,考虑枚举\(p\)计算答案,由于题目给定\(\operatorname{dis}(u,v),\operatorname{dis}(u,w),\operatorname{dis}(v,w)\),因此我们首先用解方程的方法求解\(......
  • 数据结构 玩转数据结构 13-1 红黑树与2-3树
    0课程地址https://coding.imooc.com/lesson/207.html#mid=15086 1重点关注1.1红黑树的特性  1.22-3树的特性满足二叉树性质2-3树是一棵绝对平衡的树  2课程内容2.12-3树定义每个节点有两个或三个子节点的二......
  • [oeasy]python0135_变量名与下划线_dunder_声明与赋值
    变量定义回忆上次内容变量就是能变的量上次研究了变量标识符的规则第一个字符应该是字母或下划线合法的标识符可以包括大小写字母数字下划线  还研究了字符串(str)的函数isidentifier查询字符串是否为合法标识符 ......
  • 13-CSS3属性:Flex布局图文详解
    title:13-CSS3属性:Flex布局图文详解publish:true前言CSS3中的flex属性,在布局方面做了非常大的改进,使得我们对多个元素之间的布局排列变得十分灵活,适应性非常强。其强大的伸缩性和自适应性,在网页开中可以发挥极大的作用。flex初体验我们先来看看下面这个最简单的布局:......
  • 【DP】LeetCode 132. 分割回文串 II
    题目链接132.分割回文串II思路分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律在数组的动态规划问题中,一般dp[i]都是表示以nums[i]为结尾的状态;dp[i][j]分别表示以nums1[i]和nums2[j]为结尾的状态,以此类......
  • 20201302姬正坤《网络对抗技术》Exp5 信息搜集与漏洞扫描
    《网络对抗技术》Exp5信息搜集与漏洞扫描实践目标(1)各种搜索技巧的应用(2)DNSIP注册信息的查询(3)基本的扫描技术:主机发现、端口扫描、OS及服务版本探测、具体服务的查点(以自己主机为目标)(4)漏洞扫描:会扫,会看报告,会查漏洞说明,会修补漏洞(以自己主机为目标)实践步骤一、各种搜索技......
  • ASRock Z690 Extreme WiFi 6E i7 13700KF电脑 Hackintosh 黑苹果efi引导文件
    原文来源于黑果魏叔官网,转载需注明出处。(下载请直接百度黑果魏叔)硬件型号驱动情况主板ASRockZ690ExtremeWiFi6E处理器IntelCorei713700KF已驱动内存KINGBANK2x32GBDDR4-3600CL18已驱动硬盘PredatorSSDGM70001TB已驱动显卡YESTONRX6800XT16G已驱动声卡ConexantCX8070......
  • 接口请求413 Request Entity Too large问题处理
     刚看到这个问题时,发现是请求接口时传递的参数过大,于是就在度娘上搜索了关于这个问题的处理方法;参考了好几篇文章,基本都说是配置问题最终,参考了知乎上的这篇文章:https://zhuanlan.zhihu.com/p/76679642关于上篇文章中的前端配置参数:bodyParser在express4版本中已经被弃用......
  • Investigating Div-Sum Property UVA - 11361
     定问在[A,B]中,有多少个整数本身能被m整除,各个数位上数字之和也能被m整除?  #include<iostream>#include<cstring>#include<vector>usingnamespacestd;vector<int>a;intm,f[40][105][105][2];intdfs(intx,intv1,intv2,intflg){ if(x<0) retur......