UPC 2020年夏混合个人训练第六十四场【A&C&D&G】

问题 A: 纽约

题目描述
印度洋暖流温润着纽约,四季丰沛的雨水造就了一望无际的大草原。蒙古包是纽约最独特的一道风景线,每至二月中旬,纽约的土著傣族人民又开始半年一度的转场了。
由于牲畜和行李过多,牧民Azone 不得不多次往返于两个草场之间运输家当。为了顺利转场,Azone 决定花费w 元津巴布韦币,购买一辆载重为w 的汽车。共有n 件家具需要搬运,每件家具的重量为wi。Azone 每次出发前,会搬若干件总重不超过w 的物品上车:出发前,车是空载的,Azone 会选择能搬上车的家具中最重的一件放上车(即该家具之前还未运走且放置该家具后汽车不会超载),然后在剩下的家具中继续选择一件能被搬走的最重的上车,持续装车,直至剩下的家具都塞不上车。装载完毕后,Azone 会开车运走这些家具,卸在目的地,再驾空车返回继续运送,直至转场完毕。
Azone 希望在运送次数不超过R 的情况下完成转场,求Azone 最少需要购置价值多少的车。

输入
第一行,两个整数n 和R,分别表示家具件数及最多运送次数。
第二行,若干个整数wi,表示家具重量。

输出
一行,表示答案。

样例输入
6 2
26 7 10 30 5 4

样例输出
42

提示
对于100% 的数据,1<=R, n,wi<=2000。

题解:
这是一条特殊的二分,有些复杂。当打完二分以后,一对拍,就会发现,其实它并不满足二分性。
虽然说二分出来的这个答案一定是满足题意的,但它不一定是最小的。通过比较正确答案与二分出来的答案,就会发现这两个答案之间相差不会太大,于是二分出来答案以后,再往前那么几百,判断一下前面是否有更优的答案。

// A.二分 
#include <bits/stdc++.h>
#define G getchar
using namespace std;
char ch;

void read(int& n) {
    for(n=0,ch=G();ch<'0' || ch>'9';ch=G());
    for(;'0'<=ch && ch<='9';ch=G())n=(n<<3)+(n<<1)+ch-48;
}
int n,R,a[2003],l,r,mid,ans,pre[2003],nxt[2003];

bool pd(int w)
{
    for(int i=1;i<=n;i++)
        pre[i]=i-1,nxt[i]=i+1;pre[n+1]=n;
    for(int m=1,s=0,x=n;s<n;x=pre[n+1],m++) {
        if(m>R)  return 0;
        for(int p=w;p>0 && x;x=pre[x])
            if(p>=a[x]) {
                s++;p-=a[x];
                nxt[pre[x]]=nxt[x];
                pre[nxt[x]]=pre[x];
            }
    }
    return 1;
}

int main()
{
    read(n);
	read(R);
    for(int i=1;i<=n;i++)   read(a[i]),r+=a[i],l=max(l,a[i]);
    sort(a+1,a+1+n);
    while(l<r)  {
        mid=(l+r)>>1;
        if(pd(mid))r=mid;else l=mid+1;
    }
    for(ans=l-50;ans<=l && !pd(ans);ans++);
    printf("%d",ans);
    return 0;
} 

问题 C: 山景城

题目描述
山景城毗邻雷克雅未克,位于美国东南部,高楼林立,彻夜灯明,是美国乃至世界的经济贸易中心。最有名的地标建筑当属南岸花园广场,这里不仅是洛杉矶银河队的主场,并且众多国际歌星,如二人转演员蕾哈娜,伟大的人民艺术家pdd 都曾在这里举办过演唱会。
花园广场球馆的内部由n 个独立的展厅组成,不同展厅间由n-1 条双向的走廊连接而互相可达。二月三十一号那天,花园广场球馆将会对公众开放展览文艺复兴时期的代表作品《蒙娜丽莎的假笑》,怪盗基德闻声披着夜色降临于此。不过Kris 透过馆内高端的红外线监控设施,很快便发现了基德,怪盗基德降临在s 号展厅,而Kris 此刻所在的监控室位于展厅t,Kris 想引诱基德至展厅t 以瓮中捉鳖。
从基德进入南岸花园广场球馆后的那一刻开始,双方便开始了斗智斗勇,在第i 秒钟:
? Kris 在这一秒的开始,可以进行决策:1) 不操作;2) 炸毁一条还存在的走廊,操作过后这条走廊将不复存在;3) 清除一条走廊上被怪盗基德留下标记。
? 怪盗基德在这一秒的末尾,有可能会移动:假设基德此刻正处于p 号展厅,若从p 号展厅出发通往相邻展厅的每条走廊都被画上了标记,那么基德会原地不动;否则,基德会从p 出发的未被标记的走廊中选择一个,走到对应的展厅,并在这条走廊上留下标记(若存在从p 出发的未被标记的走廊,基德必须移动,不能选择原地停留)。(注意:以上过程中Kris 先决策,决策完了之后基德再会行动)
在这一秒的博弈结束后,若怪盗进入了t 号展厅,博弈停止,否则进入下一秒的博弈。
Kris 炸毁走廊与清除标记都算作一次操作。Kris 希望用尽量少的操作次数抓住基德;而基德希望Kris 用尽量多的操作才能抓住他,并在Kris 眼皮底下逃之夭夭,以羞辱他。
由于怪盗基德过于神仙,而Kris 具有上帝视角,双方都十分清楚对方的心思,知道双方的位置,并熟知花园广场球馆的地图。此次是怪盗基德第一次造访花园广场球馆,所以所有的走廊在博弈开始前都
没有任何标记。双方都会采取最优决策,请求出Kris 操作的次数。

输入
第一行,三个整数n,t, s。
接下来n-1 行,每行两个整数ui, vi,描述一条连接ui 与vi 的通道。

输出
一行,表示答案。

样例输入
10 1 4
1 2
2 3
2 4
3 9
3 5
4 7
4 6
6 8
7 10

样例输出
4

提示
对于100% 的数据,1<= t, s, n<=10^6。

很好的图示题解

// C.模拟、矩形覆盖问题
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(x,y) (x<y?x:y)
#define max(x,y) (x>y?x:y)
using namespace std;

int a[2000001][2];
int ls[1000001],f[1000001];
int d[1000001],num[1000001];
int i,j,k,n,S,T,len,m,Find,N,l,r,mid;
bool Bz[1000001];
int D[1000001][2];
bool bz;

int p[1000001][6];
bool b[1000001];
int Len;

void New(int x,int y)
{
    len++;

    a[len][0]=y;
    a[len][1]=ls[x];
    ls[x]=len;

    num[x]++;
}

void init()
{
    memset(b,0,sizeof(b));

    Len=1;
    p[1][0]=T;
    p[1][1]=0;
    p[1][2]=0;
    p[1][3]=0;
    p[1][4]=0;
    p[1][5]=ls[T];

    while (Len)
    {
        for (; p[Len][5] && a[p[Len][5]][0]==p[Len][1]; p[Len][5]=a[p[Len][5]][1]);

        if (p[Len][5] && !b[a[p[Len][5]][0]])
        {
            Len++;
            p[Len][0]=a[p[Len-1][5]][0];
            p[Len][1]=p[Len-1][0];
            p[Len][2]=p[Len-1][2]+num[a[p[Len-1][5]][0]]-1-Bz[a[p[Len-1][5]][0]]+(a[p[Len-1][5]][0]==S);
            p[Len][3]=0;
            p[Len][4]=0;
            p[Len][5]=ls[a[p[Len-1][5]][0]];
        }

        for (; Len && !p[Len][5]; Len--)
        {
            f[p[Len][0]]=(!p[Len][4])?p[Len][2]:f[p[Len][4]];
            b[p[Len][0]]=1;
        }

        if (!Len) return;

        if (b[a[p[Len][5]][0]])
        {
            if (f[a[p[Len][5]][0]]>f[p[Len][3]])
            p[Len][4]=p[Len][3],p[Len][3]=a[p[Len][5]][0];
            else
            if (f[a[p[Len][5]][0]]>f[p[Len][4]])
            p[Len][4]=a[p[Len][5]][0];
            p[Len][5]=a[p[Len][5]][1];
        }
    }
}

void Fd()
{
    int i,h,t;

    h=0,t=1;
    D[1][0]=T;
    D[1][1]=0;
    b[T]=1;

    while (h<t)
    {
        for (i=ls[D[++h][0]]; i && !b[a[i][0]]; i=a[i][1])
        {
            D[++t][0]=a[i][0];
            D[t][1]=h;

            b[a[i][0]]=1;

            if (D[t][0]==S) break;
        }
        if (D[t][0]==S) break;
    }

    for (; t; d[++m]=D[t][0],Bz[d[m]]=1,t=D[t][1]);
}

bool pd(int t)
{
    int i,j,cut,lastcut;

    cut=0;
    fo(i,1,m-1)
    {
        lastcut=cut;

        for (j=ls[d[i]]; j; j=a[j][1])
        if (!Bz[a[j][0]])   {
            if (lastcut+f[a[j][0]]>t)
            cut++;
        }

        if (cut>i || cut>t)
        return 0;
    }

    return 1;
}

int main()
{
    scanf("%d%d%d",&n,&T,&S);
    fo(i,2,n)   {
        scanf("%d%d",&j,&k);
        New(j,k),New(k,j);
    }

    Fd();
    init();

    l=0,r=n*2;
    while (l<r)
    {
        mid=(l+r)/2;
        if (!pd(mid))    l=mid+1; 
        else    r=mid;
    }

    printf("%d\n",l);
    return 0;
}

问题 D: 话痨树

题目描述
在虚拟世界里有一种计算工具,叫做话痨树。
这种工具可以计算出小X所在国家任意两个城市的距离。
但话痨树太吵了,小X非常讨厌它,所以请穿越到异世界的你写一个工具实现话痨树的功能。这样小X就不用听话痨树唠叨了。

输入
第一行两个整数n和q,代表小X国家有n个城市,他想进行q次询问。
接下来n-1行每行三个整数u,v,k,代表城市u与城市v之间有一条双向道路,道路长度为k。
接下来q行,每行两个整数u,v,代表小X想知道u与v城市之间的距离。

输出
q行,每行是u与v城市之间的距离

样例输入
3 2
1 2 10
3 1 15
1 2
2 3

样例输出
10
25

提示
对于30%的数据,2<=n<=2000,1<=m<=2000
对于全部数据,2<=n<=10000,1<=q<=20000,1<=k<=500,m=n-1

// D.树上问题
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
 
int n,q,tot,head[10005],d[10005],dep[10005],p[10005][25];
 
struct node {
    int v, w, next;
}a[10005 << 1];
 
void dfs(int x, int pre){
    p[x][0] = pre;
    dep[x] = dep[pre] + 1;
    for (int i=1; i<=20; i++) p[x][i] = p[p[x][i - 1]][i - 1];
    for (int i=head[x]; i!=-1; i=a[i].next){
        int v = a[i].v;
        if(v == pre) continue;
        d[v] = d[x]+a[i].w;
        dfs(v, x);
    }
}
 
int LCA(int x, int y){
    if(dep[x] < dep[y])   swap(x, y);
    for (int i=20; i>=0; i--)
        if(dep[p[x][i]] >= dep[y])   x=p[x][i];
    
    if(x == y) return x;
    for (int i=20; i>=0; i--)
        if(p[x][i] != p[y][i])   x=p[x][i], y=p[y][i];
    
    return p[x][0];
}
 
int main()
{
    memset(head, -1, sizeof(head));
    scanf("%d %d", &n, &q);
    
    for (int 1, u, v, w; i<n; i++){
        scanf("%d %d %d", &u, &v, &w);
        a[tot] = node{v, w, head[u]}, head[u] = tot++;
        a[tot] = node{u, w, head[v]}, head[v] = tot++;
    }
    
    dfs(1, 0);
    for (int i=1, u, v; i<=q; i++){
        scanf("%d %d", &u, &v);
        printf("%d\n", d[u] + d[v] - 2 * d[LCA(u, v)]);
    }
    return 0;
}

问题 G: 居合

题目描述
虚拟世界要举行一个剑术大会,小Y和小X进入了决赛,决赛进行k个回合。
决赛赛制为地上有n个木桩子,每次小Y或者小X能砍其中一个柱子,他们可以选择砍掉柱子的一截(整数高度)或者是直接砍掉柱子。
每回合中,谁砍掉了最后一个柱子,谁将赢下这个回合。
机制的小Y钞能力买通了裁判,每局都让小Y先出手

输入
第一行一个数k组,
接下来每组第一行为一个整数n,第二行为n个整数,分别为每个柱子的高度h

输出
对于每个回合,如果小Y一定能赢,输出“GG”,若小Y不一定能赢,输出"gl hf"。

样例输入
3
2
1 3
2
3 3
5
1 2 3 4 5

样例输出
GG
gl hf
GG

提示
对于100%的数据:1<=k<=10,1<=n<=1001<=n<=1001<=n<=100,1<=h<=10001<=h<=10001<=h<=1000

题解:
先来讲一下异或运算:
参加运算的两个数据,按二进制位进行“异或”运算。
运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;
  即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
例如:9^5可写成算式如下: 00001001^00000101=00001100 (十进制为12)可见9^5=12

下面来引用一下大佬的证明:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

// G.博弈论 
#include <bits/stdc++.h>
using namespace std;
int k,n,a[10100];

int main()
{
	cin>>k;
	while(k--)
	{
		scanf("%d",&n);
		int check=0;
		for(int i=1; i<=n; i++)
		{
			scanf("%d",&a[i]);
			check^=a[i];
		}
		if(!check)  printf("gl hf\n");
        else  printf("GG\n");
	}
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米莱虾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值