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\n", 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\n", Serch(str));
    }

    return 0;
}
View Code

 

posted @ 2017-08-31 19:36  v9fly  阅读(158)  评论(0编辑  收藏  举报