zoukankan      html  css  js  c++  java
  • Codeforces Round #430 (Div. 2) A B 水 C dfs,思维 D trie,二进制

    Codeforces Round #430 (Div. 2)

    A    全场hack题,,有个坑,直接判 l~r 是否在 x*k ~ y*k 之间就挂了,因为并不是 x*k~y*k 之间所有数都可以。如:7,7,3,6,2 。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 200005;
    
    ll  l, r, x, y, k;
    int main()
    {
        scanf("%lld%lld%lld%lld%lld", &l, &r, &x, &y, &k);
        for(ll  i = x; i<=y; ++i)
        {
            ll  c = i*k;
            if(l<=c && c<=r) return 0*printf("YES");
        }
        puts("NO");
    
        return 0;
    }
    View Code

    B    水

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 200005;
    const  double  eps = 1e-6;
    
    double dis(double x1, double y1, double x2, double y2)
    {
        return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );
    }
    
    int n, ans;
    double r, d, xi, yi, ri;
    bool  check(double x, double y, double r2)
    {
        double a1 = dis(x, y, 0, 0) + ri;
        double a2 =  dis(x, y, 0, 0) - ri;
        if( a2>=(r-d)  &&  r>=a1) return true;
        else return  false;
    }
    int main()
    {
        scanf("%lf%lf", &r, &d);
        scanf("%d", &n);
        rep(i,1,n)
        {
            scanf("%lf%lf%lf", &xi, &yi, &ri);
            if(check(xi, yi, ri))  ++ans;
        }
        printf("%d
    ", ans);
    
        return 0;
    }
    View Code

    C     dfs

    题意:一棵树,对于每个点 x ,可以删去从根节点 1 到 x 这条链上的一个点,或者不删,然后问这条链上所有数的gcd最大可以是多少。

    tags:

    考虑 dfs 搜到节点 u 时,设 fa 是 u 的父亲节点,我们有三种选择: 

    1】选下这个数a[u],且点1到点 fa 之间的所有点都选上。   

    2】不选这个数a[u],且点1到点 fa 之间的所有点都选上。   

    3】选下这个数,且点1到点 fa 之间删去一个点。

    用一个集合set[u] 存下点1到点 fa 之间删去一个点可能得到的所有gcd,然后在搜索时根据set[fa]更新set[u]即可。

    因为要求的是gcd,会有很多重复的数,所以se[u]是不会增长很快的。

    //  CF  C
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 200005;
    
    int n, a[N], x, y, ans[N];
    vector<int > G[N];
    set<int > se[N];
    void Init()
    {
        rep(i,0,N-1) G[i].clear(), se[i].clear();
        mes(ans, 0);
    }
    void dfs(int u, int fa, int now)
    {
        ans[u] = max(ans[u], now);
        se[u].insert(now);
        for(auto v : se[fa])
        {
            int  g = __gcd(v, a[u]);
            se[u].insert(g);
            ans[u] = max(ans[u], g);
        }
        now = __gcd(now, a[u]);
        ans[u] = max(ans[u], now);
        for(auto v : G[u]) if(v!=fa)
        {
            dfs(v, u, now);
        }
    }
    int main()
    {
        scanf("%d", &n);
        Init();
        rep(i,1,n) scanf("%d", &a[i]);
        rep(i,1,n-1)
        {
            scanf("%d%d", &x, &y);
            G[x].PB(y);  G[y].PB(x);
        }
        dfs(1, 0, 0);
        rep(i,1,n) printf("%d ", ans[i]);
        puts("");
    
        return 0;
    }
    View Code

    D     trie

    题意:有 n 个数 ai,m个询问,每次询问有一个 x,表示这 n 个数都变为 ai^x,然后求异或后的 mex。

    tags:第一次做这种题,才知道可以用字典树。。

    首先要想到 m 次询问可以累积,即第一次异或 x1,第二次异或 x2,那第二次就可以直接求序列异或上 (x1^x2) 的答案。这样就不需要每次更新序列。

    然后就是要怎么求这个序列异或上一个值后的 mex ?

    摘自大神博客很多二进制关于异或求最值的问题,都可以转换为字典树来求,然后在字典树上往最左边或者最右边跑,使得结果达到最值。

    对于这个题,假如我们要异或上 x ,那把序列中的数按二进制位建好字典树后,把 x 按二进制位从字典树根节点往下走,在每一层尽量往小的那一边走。

    如走到第 i 层时,x 二进制位是 0,那我们就看 0 结点子树是否满了,没满就往 0 子树走,满了就往 1 子树走;  反之如第 i 层时 x 二进制位是 1,异或一下则表示这一层要反一下,即看 1 子树是否满了。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 300005;
    
    struct trie
    {
        int cnt;  bool is;
        trie  *child[2];
        trie()  {
            mes(child, NULL);
            cnt = 0,  is = false;
        }
    };
    trie  *root = new trie,  *current;
    void Insert(char *str)
    {
        current = root;
        rep(i,0,19)
        {
            int j = str[i] - '0';
            if(current->child[j]==NULL) current->child[j] = new trie;
            current = current->child[j];
            ++current->cnt;
            if(current->cnt == 1<<(19-i))  current->is = true;
        }
    }
    int Serch(char *str)
    {
        int ans = 0;
        current = root;
        rep(i,0,19)
        {
            int j = str[i] - '0';
            ans <<= 1;
            if(j==0)
            {
                rep(l,0,1) if(current->child[l]==NULL) current->child[l] = new trie;
                if(current->child[0]->is) current = current->child[1], ans++;
                else  current = current->child[0];
            }
            else
            {
                rep(l,0,1) if(current->child[l]==NULL) current->child[l] = new trie;
                if(current->child[1]->is) current = current->child[0], ans++;
                else  current = current->child[1];
            }
        }
        return ans;
    }
    
    int n, m, ai, x;
    bool vis[N];
    char str[30];
    void getstr(int y)
    {
        per(i,19,0)
        {
            int y2 = 1<<i;
            if(y2<=y) y-=y2, str[19-i]='1';
            else  str[19-i]='0';
        }
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        rep(i,1,n)
        {
            scanf("%d", &ai);
            if(vis[ai]==0) {
                getstr(ai);
                Insert(str);
            }
            vis[ai] = 1;
        }
        int s = 0;
        rep(i,1,m)
        {
            scanf("%d", &x);
            s ^= x;
            getstr(s);
            printf("%d
    ", Serch(str));
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    git和github的使用
    C语言 -- 链表操作
    数据结构之表达式求值(C++版)
    数据结构之一元多项式加法(C++版)
    数据结构之邻接矩阵(C++版)
    数据结构之二叉树,赫夫曼树(C++版)
    数据结构之循环队列(C++版)
    数据结构之顺序栈(C++版)
    数据结构之单链表(C++版)
    数据结构之顺序表(C++版)
  • 原文地址:https://www.cnblogs.com/sbfhy/p/7460136.html
Copyright © 2011-2022 走看看