Codeforces Round #613 (Div. 2)(D二進制字典樹dfs,E區間查詢連續的段1)

Codeforces Round #613 (Div. 2)

D. Dr. Evil Underscores

題意很簡單:

就是這麼簡單的題意我還看錯題了,我以爲是求X。。。然後就不可做了。

然而題目是求

這個,最大值中的最小值。。

那就可做了。有一道類似的題:143. 最大異或對(字典樹)acwing  一樣的思路

具體做法就是 在二進制字典樹上跑dfs,當  當前節點既有0,又有1時,那麼ans這位上一定是1,否則就是0。。。直接dfs跑一遍字典樹即可。。。我感覺我像個傻子一樣,老看錯題。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+10;

int a[N],n,ans,cnt;
int ne[N*35][2];
void dfs(int o,int id,int val)
{
    if(id<0) {
        ans=min(ans,val);
        return ;
    }
    if(ne[o][0]&&ne[o][1]){
        dfs(ne[o][0],id-1,val^(1<<id));
        dfs(ne[o][1],id-1,val^(1<<id));
    }
    else if(ne[o][1]) dfs(ne[o][1],id-1,val);
    else dfs(ne[o][0],id-1,val);

}
void in(int x)
{
    int id=0;
    for(int i=30;~i;--i){
        int to=0;
        if(x&(1<<i)){
            to=1;
        }

        if(!ne[id][to]){
            ne[id][to]=++cnt;
        }

        id=ne[id][to];
    }
}
int main()
{
    cin>>n;
    rep(i,1,n) {
        scanf("%d",&a[i]);
        in(a[i]);
    }
    ans=1<<30;

    dfs(0,30,0);

    printf("%d\n",ans);
}

E. Delete a Segment

參考題解

很妙的做法~

/*
區間查詢被覆蓋的區間有多少個連續的一段1
*/
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int sum[10*N],add[10*N],X[10*N],len,b[N];
struct node
{
    int l,r;
}a[N];
int n;
void init(int len)
{
    for(int i=0;i<=len;++i){
        add[i]=sum[i]=0;
    }
}
int getid(int x)
{
    return lower_bound(X+1,X+1+len,x)-X;
}
int main()
{
    int _;cin>>_;while(_--){
        scanf("%d",&n);

        len=0;
        for(int i=1;i<=n;++i){
            scanf("%d%d",&a[i].l,&a[i].r);
            a[i].l=2*a[i].l,a[i].r=a[i].r*2;
            X[++len]=a[i].l-1;X[++len]=a[i].l;X[++len]=a[i].l+1;
            X[++len]=a[i].r-1;X[++len]=a[i].r;X[++len]=a[i].r+1;
        }
        sort(X+1,X+1+len);
        len=unique(X+1,X+1+len)-X-1;
        init(len);
        for(int i=1;i<=n;++i){
            a[i].l=getid(a[i].l);a[i].r=getid(a[i].r);
            //printf("l:%d r:%d\n",a[i].l,a[i].r);
            add[a[i].l]++;add[a[i].r+1]--;
        }

        int pre=0;
        for(int i=1;i<=len;++i){
            pre+=add[i];
            b[i]=pre;
        }


        for(int i=1;i<=len;++i){
            if(b[i]==1&&b[i-1]!=1) sum[i]=sum[i-1]+1;
            else sum[i]=sum[i-1];
            //printf("%d ",b[i]);
        }
        //puts("");

        pre=0;
        for(int i=1;i<=len;++i){
            if(b[i]==0&&b[i-1]!=0) pre++;
        }

        int ans=pre-1;
        for(int i=1;i<=n;++i){
            int t=sum[a[i].r]-sum[a[i].l-1];
            if(b[a[i].l-1]==0&&b[a[i].l]==1) t--;
            if(b[a[i].r+1]==0&&b[a[i].r]==1) t--;
            ans=max(ans,t+pre);
        }
        printf("%d\n",ans);

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章