HDU 4446 IT Companies

题目描述:一堆公司,每个公司有个子公司,公司编号为i,子公司编号为-i。每个公司的人数比子公司多,两个公司,如果一个的人数比另一个多,那么他的子公司的人数也多。

然后求一个构造,使得编号比i这个公司大的公司中,人数比他多的是c[i],同时编号比他的子公司大的子公司中,人数比他的子公司多的也是c[i]

解法: 以下来自官方题解


1.一开始开2个队列a,ba为答案队列,b为临时队列

2.找出当最小的C值为C[k](相同时取k最小的)

a)C[k]=0:将k加入a-k加入b。在C序列中删除元素C[k],并将C[1]C[k-1]减一。

b)C[k]>0:将b队首的元素p取出加入a,并将C[-p+1]c[n]减一。

重复做直到所有元素进入a或者b

3.将b接在a后面,倒序就是答案序列


无解有两种情况:

1C中出现了负数。

2.出现2b情况时b为空


#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define prt(k) cout<<#k" = "<<k<<endl;
const int N = 100010<<2;
const int inf = 0x3f3f3f3f;

int c[N];
struct data
{
    int v, id;
    data() {}
    data(int a, int b) { v=a, id=b; }
};
data tree[N];
int add[N];
int ans[N];
int n,m,cnt;

data Min(data x, data y)
{
    if(x.v<y.v || (x.v==y.v&&x.id<y.id))
        return x;
    else
        return y;
}
void pushup(int o)
{
    tree[o]=Min(tree[o*2],tree[o*2+1]);
}
void build(int l, int r, int o)
{
    add[o]=0;
    if(l==r)
    {
        tree[o]=data(c[l], l);
        return ;
    }
    int m=(l+r)/2;
    build(l,m,o*2);
    build(m+1,r,o*2+1);
    pushup(o);
}
void pushdown(int l, int r, int o)
{
    if(l==r) return;
    if(add[o])
    {
        add[o*2]+=add[o];
        add[o*2+1]+=add[o];
        tree[o*2].v+=add[o];
        tree[o*2+1].v+=add[o];
        add[o]=0;
    }
}
void update(int L,int R,int v, int l,int r,int o)
{
    if(L<=l&&r<=R)
    {
        if(v==inf)
        {
            tree[o].v = inf;
            add[o]=0;
            return;
        }
        tree[o].v+=v;
        add[o]+=v;
        return;
    }
    pushdown(l,r,o);
    int m=(l+r)/2;
    if(L<=m) update(L,R,v, l,m,o*2);
    if(m<R) update(L,R,v, m+1,r,o*2+1);
    pushup(o);
}
data query(int L,int R, int l,int r,int o)
{
    if(L<=l && r<=R) return tree[o];
    pushdown(l,r,o);
    int m=(l+r)/2;
    data ans=data(inf,0);
    if(L<=m) ans=Min(ans,query(L,R, l,m,o*2));
    if(m<R) ans=Min(ans,query(L,R, m+1,R,o*2+1));
    return ans;
}
#include<deque>
#include<queue>
int main()
{
    while(scanf("%d",&n)==1)
    {
        if(n==0) break;
        bool flag = 1;
        for(int i=1;i <=n;i++)
        {
            scanf("%d",c+i);
            if(c[i]<0)
            {
                puts("Impossible");
                flag = 0;
            }
        }
        if(!flag) continue;
        build(1,n,1);
        queue<int> a,b;
        cnt=n; int t=0;
        while(cnt)
        {
            data u = query(1,n, 1,n,1);
            int k=u.id;
            if(u.v==inf) break;
            if(u.v==0 )
            {
                ans[t++] = k;
                b.push(-k);
                update(k,k,inf, 1,n,1);
                if(k>1) update(1,k-1,-1, 1,n,1);
                cnt--;
            }
            else if(u.v > 0)
            {
                if(b.empty())
                {
                    flag = 0;
                    break;
                }
                int p=b.front();
                ans[t++]=p;
                b.pop();
                if(-p+1<=n&&-p+1>=1) update(-p+1,n,-1, 1,n,1);
            }
        }
        if(flag==false)
        {
            puts("Impossible");
            continue;
        }
        while(!b.empty())
        {
            ans[t++]=b.front();
            b.pop();
        }
        n = 2*n;
        for(int i=n-1;i>0;i--)
            printf("%d ",ans[i]);
        printf("%d \n",ans[0]);
    }
}


你可能感兴趣的:(HDU 4446 IT Companies)