洛谷 3528 libreoj 2170 [POI2011]PAT-Sticks

题意简述

给你一些木棍,每个木棍有长度和颜色。输出一种方案,选择三个木棍,使得颜色不一样且能拼成一个三角形。开,多解输出任意一个。

木棍数量,颜色数量

思路框架

按长度排序,每次更新答案。

具体思路

首先木棍显然是无序的。无序的问题,就先无脑排序一下(如果复杂度能承受)。没问题的。

然后我们用一个长度为的数组表示答案。每次枚举,表示我们必须要把放到答案中(如果合法)

如果我们的答案中已经有一个和同颜色的木棍,那么我们肯定是换掉来的好,因为的长度肯定大于这根木棍的长度。(我们排过序,记得么)

然后如果没有相同的颜色,就用它换掉最短的那个木棍。这样显然也是更好的。

然后检测一下是否合法。如果合法,就输出答案,然后直接退出程序即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 1666666
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)

struct node
{
int col,len;
}a[N];int cnt=0;
bool operator<(node a,node b){return a.len<b.len;}
int k;
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Input()
{
R1(k);
cnt=0;
F(i,1,k)
{
int n;R1(n);
F(j,1,n)
{
int len;R1(len);
a[++cnt]=(node){i,len};
}
}
}

node ans[4];
void Soviet()
{
sort(a+1,a+cnt+1);
FK(ans);

F(i,1,cnt)
{
bool flag=false;
F(j,1,3)
{
if (a[i].col==ans[j].col)//相同颜色
{
ans[j].len=a[i].len;
flag=true;
}
}

if (!flag)//没有相同的颜色
{
ans[1]=a[i];//换掉最小的
}
sort(ans+1,ans+4);
if (ans[1].len+ans[2].len>ans[3].len)//检测
{
F(j,1,3) printf("%d %d ",ans[j].col,ans[j].len);
putchar('\n');
return;
}
}
puts("NIE");
}

#define Flan void
Flan IsMyWife()
{
Input();
Soviet();
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}
w