ZOJ3963 【gay gay 的贪心】

来源:互联网 发布:中国社科院大学知乎 编辑:程序博客网 时间:2024/04/25 20:03

(这个题的idea好棒啊)

思路:

一个值 val 的插入最好就是在一个最接近他的值的结点x (权值x <= val) 上插入。

so,拿个 set 维护一下所有的结点,每次二分找一下。
还有要维护结点所能插的位置数量,不能插了要删除。

PS: set.upper_bound()好像是log(N)的

//#include <bits/stdc++.h>#include<iostream>#include<cstdio>#include<cstring>#include<stack>#include<set>#include<map>#include<queue>#include<cmath>#include<algorithm>typedef long long LL;using namespace std;//#pragma comment(linker, "/STACK:102400000,102400000")const int N=1e5+10;int n;int node[N],cnt[N];         //node[] 代表结点位于树的编号,cnt[]代表该结点能插的个数vector<int>ans[N];          //存答案set<int>shu;int num;void init(){    num = 0;    for(int i=0;i<=n;i++){        ans[i].clear();        cnt[i]=node[i]=0;    }    shu.clear();}void solve(int x,int pos){    set<int>::iterator it;    it=shu.upper_bound(x);    if(it == shu.begin()){            shu.insert(x);            cnt[x] = 2;            node[x] = num;            ans[num].push_back(pos);            num++;    }    else{        it--;        if(x != *it){            cnt[*it]--;            node[x] = node[*it];            if(!cnt[*it]) shu.erase(it);            shu.insert(x);            cnt[x] = 2;            ans[node[x]].push_back(pos);        }        else        {            cnt[x]++;            ans[node[x]].push_back(pos);        }    }}int main(){    int T,x;    scanf("%d",&T);    while(T--){        init();        scanf("%d",&n);        for(int i=1;i<=n;i++){            scanf("%d",&x);            solve(x,i);        }        printf("%d\n",num);        for(int i=0;i<num;i++)        {            int sz = ans[i].size();            printf("%d",sz);            for(int j=0;j<sz;j++)                printf(" %d",ans[i][j]);            puts("");        }    }    return 0;}




0 0
原创粉丝点击