zoukankan      html  css  js  c++  java
  • CF1282E

    在机房和 Alex_Wei 无聊做 2500 的题,做不动然后做这个 2400 的题。然后吊打他了,他到 8:00 下课还没做出来,而我则在 8:01 AC 了。吊打 2512 GM,爽(

    学校 407 机房电脑上竟然没有 devc++,于是代码是在 CF 上的 custom test 里写的/kk


    Portal

    注意到,对于任意一种三角剖分方法,一定有一个三角形是连接相邻三个顶点的,这是异常显然的。考虑从这个三角形入手,显然这个三角形连接的三个点中间那个只会在共 (3(n-2)) 个数中出现一遍。于是我们可以找到这个出现一遍的点(如果有多个则选择任意一个),将这个三角形删掉,这样得到了一个大小为 (n-1) 的多边形,咦,可以顺着这个思路归纳下去了。

    就一直删直到大小为 (3) 为止。那么剖分顺序显然就是删除顺序。至于顶点顺序,考虑若 (n-1) 的答案是序列 (a),然后删掉的那个三角形从左到右分别是 (x,y,z)。那么显然在 (a)(x,z) 是(环形)相邻的,那么只需要将 (y) 插入它们两个之间就可以得到 (n) 的顶点顺序。

    接下来考虑实现。难点在于如何每次快速找到仅出现一次的点,和如何快速在两个数中间插入一个数。

    • 如何每次快速找到仅出现一次的点:考虑类似拓扑排序的流程,维护一个队列,里面装当前没被处理过的仅出现一次的点。然后用当前点去更新别人出现次数,如果有被减成 (1) 的就压入。由于保证有解,所以肯定能进行到最后。
    • 如何快速在两个数中间插入一个数:考虑暴力平衡树(大雾)。考虑链表。但是链表不支持随机访问啊,没关系,你会发现就算支持随机访问你也不会做。注意到你不需要根据下标访问,你只需要根据值来访问(你需要找到 (x)(z)),而值所对应地址显然是不会变的,于是每插入一个值就存下它的地址就好了。

    线性。

    (发现缩进是空鸽哦)

    #include<bits/stdc++.h>
    using namespace std;
    #define mp make_pair
    #define X first
    #define Y second
    #define pb push_back
    const int N=100000;
    int n;
    int a[N+1],b[N+1],c[N+1];
    vector<int> hav[N+1];
    bool del[N+1];
    int cnt[N+1];
    vector<pair<int,pair<int,int> > > v;
    list<int>::iterator it[N+1];
    list<int>::iterator operator+(list<int>::iterator x,int){return ++x;}
    void mian(){
        cin>>n;
        //clear
        for(int i=1;i<=n;i++)hav[i].clear();
        memset(del,0,sizeof(del)),memset(cnt,0,sizeof(cnt));
        v.clear();
        for(int i=1;i<=n-2;i++)
            scanf("%d%d%d",a+i,b+i,c+i),
            cnt[a[i]]++,cnt[b[i]]++,cnt[c[i]]++,
            hav[a[i]].pb(i),hav[b[i]].pb(i),hav[c[i]].pb(i);
        queue<int> q;
        for(int i=1;i<=n;i++)if(cnt[i]==1)q.push(i);
        vector<int> ans2;
        for(int i=1;i<n-2;i++){
            int x=q.front();
            q.pop();
            for(int i=0;i<hav[x].size();i++)if(!del[hav[x][i]]){
                int fd=hav[x][i];
                ans2.pb(fd);
                if(b[fd]==x)swap(a[fd],b[fd]);
                else if(c[fd]==x)swap(a[fd],c[fd]);
                v.pb(mp(x,mp(b[fd],c[fd])));
                del[fd]=true;
                if(--cnt[b[fd]]==1)q.push(b[fd]);
                if(--cnt[c[fd]]==1)q.push(c[fd]);
                break;
            }
        }
        list<int> lis;
        for(int i=1;i<=n-2;i++)if(!del[i]){
            ans2.pb(i);
            lis.pb(a[i]),it[a[i]]=--lis.end();
            lis.pb(b[i]),it[b[i]]=--lis.end();
            lis.pb(c[i]),it[c[i]]=--lis.end();
        }
        for(int i=n-4;~i;i--){
            int x=v[i].X,l=v[i].Y.X,r=v[i].Y.Y;
            if(it[l]+1==it[r]||it[l]==--lis.end()&&it[r]==lis.begin())
                lis.insert(it[l]+1,x),it[x]=it[l]+1;
            else lis.insert(it[r]+1,x),it[x]=it[r]+1;
        }
        for(list<int>::iterator i=lis.begin();i!=lis.end();i++)printf("%d ",*i);puts("");
        for(int i=0;i<ans2.size();i++)printf("%d ",ans2[i]);puts("");
    }
    int main(){
        int testnum;
        cin>>testnum;
        while(testnum--)mian();
        return 0;
    }
    
  • 相关阅读:
    JavaScript箭头函数 和 generator
    JavaScript闭包
    JavaScript高阶函数 map reduce filter sort
    JavaScript函数定义和调用 变量作用域
    python实现遗传算法求函数最大值(人工智能作业)
    PAT 1003
    制作U盘启动盘之后的恢复
    异步IO
    CCF201703-3 Markdown
    SQLAlchemy
  • 原文地址:https://www.cnblogs.com/ycx-akioi/p/cf1282e-solution.html
Copyright © 2011-2022 走看看