2018-2019 ICPC, NEERC, Southern Subregional Contest B - Berkomnadzor [contest/1070]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z591826160/article/details/83268189

B - Berkomnadzor [contest/1070]

题面

在这里插入图片描述

思路

考虑二进制,屏蔽只是不影响后 32 x 32-x 位的内容,每一个区间的长度都为 2 i 2^i ,并且合并操作一定是贪心的,能把区间扩大就尽量扩大。

YY了一下使用字典树比较好,用字典树也做过很多最小重复前缀之类的东西,思路很相似,把被禁止的网络在字典树上尽量往根部移动。

(貌似见过类似的题目,忘记在哪里了 2016北京区域赛B题好像也有一个类似的 不过当时太菜 根本没思路)

代码

const int maxn = 5e6+7;
const int inf  = 0x3f3f3f3f;
const int mod  = 1e9 + 7;
const int none = -1;
const LL linf  = (LL)inf << 32 | inf;

char now[maxn];
int trie[maxn][2],fa[maxn],signs[maxn],cnt=0;
vector<ll>ans;
bool ok=true;
void insert(int len,ll id,int sign){
    int rt=0;
    per(i,32,32-len){
        int nxt=(id>>i)&1;
        if(!trie[rt][nxt]){
            trie[rt][nxt]=++cnt;
            fa[cnt]=rt;
        }
        rt=trie[rt][nxt];
    }
    if(signs[rt]==-1*sign)
        ok=false;
    signs[rt]=sign;
    return ;
}
void read(){
    scanf("%s",now);
    int sign = now[0]=='-'?-1:1;
    ll a,b,c,d,x=32;
    sscanf(now+1,"%lld.%lld.%lld.%lld",&a,&b,&c,&d);
    int len=strlen(now);
    rep(i,0,len)
        if(now[i]=='/')
            sscanf(now+i+1,"%lld",&x);
    ll id=(a<<24)+(b<<16)+(c<<8)+d;
    insert(x,id,sign);
}
void getans(int rt,int len,ll id){
    if(signs[rt]==-1){
        ans.pb(id);ans.pb(len);
        return ;
    }
    if(trie[rt][0])
        getans(trie[rt][0],len+1,id);
    if(trie[rt][1])
        getans(trie[rt][1],len+1,id|(1ll<<(31-len)));
}
int main(){
    int n;
    rd(n);
    rep(i,0,n)
        read();
    rep(i,0,cnt+1){
        if(signs[i]!=-1)continue;
        int rt=i;
        while(fa[rt]){
            if(signs[fa[rt]]==1)ok=false;
            rt=fa[rt];
        }
    }
    rep(i,0,cnt+1){
        if(signs[i]!=1)continue;
        int rt=i;
        while(fa[rt]){
            if(signs[fa[rt]]==-1)ok=false;
            else signs[fa[rt]]=1;
            rt=fa[rt];
        }
    }
    rep(i,0,cnt+1){
        if(signs[i]!=-1)continue;
        int rt=i;
        while(fa[rt]&&signs[fa[rt]]!=1){
            signs[rt]=0;
            signs[fa[rt]]=-1;
            rt=fa[rt];
        }
    }
    if(!ok){
        puts("-1");
    } else {
        getans(0,-1,0);
        printf("%d\n",ans.size()/2);
        for(int i=0;i<ans.size();i+=2){
            ll now=ans[i];
            debug(now);
            ll d=now&((1<<8)-1);
            now>>=8;
            ll c=now&((1<<8)-1);
            now>>=8;
            ll b=now&((1<<8)-1);
            now>>=8;
            ll a=now&((1<<8)-1);
            printf("%lld.%lld.%lld.%lld/%lld\n",a,b,c,d,ans[i+1]);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/z591826160/article/details/83268189
今日推荐