文明大学生

数学公式

D - Polyline Simplification Kattis - simplification


题意:给你n+1个点,让你剩下m+1个点   。

删除的方法是,取出来构成最小三角形的中间点,去除那个点,最后输出去除点的顺序。

解法:先求出来每个三角形的面积,用set  排序或者用优先队列 都OK 每次取出来最小值Pop 并且更新左右点

两端点需要特殊处理下

#include <bits/stdc++.h>
#define FRER() freopen("i.txt","r",stdin);
using namespace std;
const int maxn=2e5+100;
/*
这道题有用线段树做的,说明人家线段树用的就是好,没有任何办法


*/
struct node
{
    int index;
    int area;//用整数,避免误差
    bool operator<(const node &a)const
    {
        if(area==a.area)
            return index<a.index;
        return area<a.area;
    }
};
set<node>se;
set<node>::iterator it;
int L[maxn],R[maxn];
int x[maxn],y[maxn];
int Area[maxn];
int getArea(int i)
{
    int p=i,p1=L[i],p2=R[i];
    return abs((x[p1]-x[p])*(y[p2]-y[p])-(y[p1]-y[p])*(x[p2]-x[p]));
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    scanf("%d%d",&x[0],&y[0]);
    for(int i=1;i<=n;i++)
    {scanf("%d%d",&x[i],&y[i]);
    L[i]=i-1;
    R[i]=i+1;
    }
    node node1;
    for(int i=1;i<n;i++)
    {
        node1.index=i;
        node1.area=getArea(i);
        Area[i]=getArea(i);
        se.insert(node1);
    }
    int t=n-m;
    while(t--)
    {
        it=se.begin();
        int p=(*it).index;
        se.erase(it);
        L[R[p]]=L[p];
        R[L[p]]=R[p];
        if(L[p]!=0)
        {
            node1.index=L[p];
            node1.area=Area[L[p]];
            it=se.find(node1);
            se.erase(it);

            node1.index=L[p];
            node1.area=getArea(L[p]);
            Area[L[p]]=node1.area;
            se.insert(node1);
        }
        if(R[p]!=n)
        {
             node1.index=R[p];
            node1.area=Area[R[p]];
            it=se.find(node1);
            se.erase(it);

            node1.index=R[p];
            node1.area=getArea(R[p]);
            Area[R[p]]=node1.area;
            se.insert(node1);
        }
        printf("%d\n",p);
    }
    return 0;
}

 

posted on 2019-10-26 20:58  文明大学生  阅读(176)  评论(0编辑  收藏  举报

导航