Sticks
POI2011
题意
1.有若干木棍,每根木棍有特定的颜色和长度
2.问能否找到三条颜色不同的木棍构成一个三角形
(注意这里所说的三角形面积要严格大于0)
解
1.先把木棍从小到大排
2.然后把相邻颜色相同的合并(记录这种颜色此时能取到的最小值和最大值)
这时剩下的相邻两个颜色必然不同
3.从前往后枚举相邻两种颜色(指的是从先前预处理的数组中选)
靠后的那种颜色作为最长边©
靠前的那种颜色作为此长边(b)
再从前面找出一根颜色不同的作为最短边(a)
构成三角形必须满足 a+b>c
就是然c尽量小,a,b尽量大
这就是为什么取相邻的两种颜色
这时的c是满足条件时最小的c(取这种颜色中的最小值)
这时的b是满足条件时最大的b(取这种颜色的最大值)
a想要快速查询就必须时刻维护前面的三条最长链(颜色不同)
具体代码
#include<bits/stdc++.h>
using namespace std;
int K,n,len;
struct node {
int c,l,r;
bool operator< (const node&tmp)const {
return l<tmp.l;
}
} A[1000005];
int mx[3],id[3];
void init() {
mx[0]=mx[1]=mx[2]=-1e9;
id[0]=id[1]=id[2]=0;
}
void insert(int c,int l) {
for(int i=0; i<3; i++) {
if(id[i]==c) {
mx[i]=l;
return;
}
}
mx[2]=mx[1],id[2]=id[1];
mx[1]=mx[0],id[1]=id[0];
mx[0]=l,id[0]=c;
}
int query(int a,int b) {
for(int i=0; i<3; i++) {
if(id[i]!=a&&id[i]!=b)return i;
}
}
int main() {
int a,x;
scanf("%d",&K);
for(int i=1; i<=K; i++) {
scanf("%d",&a);
while(a--) {
scanf("%d",&x);
A[++n]=(node) {
i,x
};
}
}
sort(A+1,A+1+n);
len=0;
for(int i=1; i<=n; i++) {
if(A[i].c!=A[i-1].c) {
A[++len].c=A[i].c;
A[len].l=A[len].r=A[i].l;
} else {
A[len].r=A[i].l;
}
}
bool flag=0;
for(int i=1; i<len; i++) {
int p=query(A[i].c,A[i+1].c);
if(mx[p]+A[i].r<=A[i+1].l) {
insert(A[i].c,A[i].r);
} else {
printf("%d %d %d %d %d %d\n",id[p],mx[p],A[i].c,A[i].r,A[i+1].c,A[i+1].l);
flag=1;
break;
}
}
if(!flag)printf("NIE\n");
return 0;
}