POI2011 Sticks

Sticks

POI2011

题意

1.有若干木棍,每根木棍有特定的颜色和长度

2.问能否找到三条颜色不同的木棍构成一个三角形
(注意这里所说的三角形面积要严格大于0)

1.先把木棍从小到大排

2.然后把相邻颜色相同的合并(记录这种颜色此时能取到的最小值和最大值)

这时剩下的相邻两个颜色必然不同

3.从前往后枚举相邻两种颜色(指的是从先前预处理的数组中选)
靠后的那种颜色作为最长边©
靠前的那种颜色作为此长边(b)
再从前面找出一根颜色不同的作为最短边(a)

构成三角形必须满足 a+b>c
就是然c尽量小,a,b尽量大

这就是为什么取相邻的两种颜色

这时的c是满足条件时最小的c(取这种颜色中的最小值)

这时的b是满足条件时最大的b(取这种颜色的最大值)

a想要快速查询就必须时刻维护前面的三条最长链(颜色不同)

具体代码

#include
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;
}

你可能感兴趣的:(POI题解,POI)