zoukankan      html  css  js  c++  java
  • codeforces round #414 div1+div2

    A:判断一下就可以了

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int a, b, c, n;
    ll ans;
    int main()
    {
        scanf("%d%d%d%d", &a, &b, &c, &n);
        for(int i = 1; i <= n; ++i)
        {
            int x; scanf("%d", &x);
            if(x > b && x < c) ++ans;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    View Code

    B:1:sqrt(2)-1....

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    double f;
    int main()
    {
        scanf("%d%lf", &n, &f);
        double t = f / (double)sqrt(n);
        for(int i = 1; i < n; ++i)
        {
            printf("%.15f ", t * (double)sqrt(i));
        }
        return 0;
    }
    View Code

    C:贪心,第一个字符串只用前n-[n/2]个,后一个字符串只用后[n/2]个,每个字符串用两个指针,如果第一个字符串最小的比第二个字符串最大的小,那么第一个人将最小的字符放在最靠前的位置,同理第二个人将最大的字符放在最前的位置,如果第一个人最小的字符比第二个人最大的字符大,那么就把他最大的字符放在末尾,第二个人则将最小的字符放在末尾。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 300010;
    int n;
    int cnt1[N], cnt2[N], ans[N];
    char s[N], t[N];
    int main()
    {
        scanf("%s%s", s + 1, t + 1); n = strlen(s + 1);
        for(int i = 1; i <= n; ++i) ++cnt1[s[i] - 'a'];
        for(int i = 1; i <= n; ++i) ++cnt2[t[i] - 'a'];
        int pos1 = 0, pos2 = 25, l = 0, r = n + 1; 
        for(int i = 1; i <= n; ++i)
        {
            while(cnt1[pos1] == 0) ++pos1;
            while(cnt2[pos2] == 0) --pos2;
            if(i % 2 == 1)
            {
                if(pos1 < pos2) ans[++l] = pos1;
                else ans[--r] = pos1;
                --cnt1[pos1];
            }
            else
            {
                if(pos1 < pos2) ans[++l] = pos2;
                else ans[--r] = pos2;
                --cnt2[pos2];
            }
        } 
        for(int i = 1; i <= n; ++i) printf("%c", (char)(ans[i] + 'a'));
        return 0;
    }
    View Code

    D:重点在于会有相同的颜色,如果没有的话,那么直接染色就可以了,因为这样限制是唯一的,一个点颜色为i,相邻只能用两种颜色i-1和i+1,那么很好办。这里我们用一个巧妙的办法去除相同颜色,一个点将自己放入自己的邻接表中,然后排序邻接表,如果两个点的邻接表相同那么他们肯定相邻,那么这两个点的颜色相同。我们设一个点的颜色为i,另一个点的颜色为i+1,那么相邻的点的颜色只能等于i或i+1,如果等于i-1或i+2的话肯定和两个点中的一个矛盾,那么既然所有的邻居都等于i或i+1,那么我们不妨把那个颜色为i+1的点颜色换为i,很显然不矛盾。然后我们就把颜色能够相同的点分类,画成一个大点,重新编号,构图,两个新的点相邻当且仅当他们的点集中有相邻的点,也就是说这两个点集是相邻的。这里我们可以知道如果一个新的点的度数>=3或者有环就是无解,否则直接染色。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 600010, MaxCH = 20000000;
    int n, m, pos, len;
    char CH[MaxCH];
    vector<int> G[N];
    int fa[N], color[N], Hash[N], h[N], u[N], v[N], used[N], vis[N];
    inline int read()
    {
        int x = 0;
        while(CH[pos] < '0' || CH[pos] > '9') ++pos;
        while(CH[pos] >= '0' && CH[pos] <= '9') x = x * 10 + CH[pos++] - '0';
        return x; 
    }
    namespace dsu 
    {
        inline int find(int x) { return x == fa[x] ? x : find(fa[x]); }
        inline void connect(int x, int y)
        {
            int u = find(x), v = find(y);
            if(u == v) return;
            fa[u] = v;
        }
    } using namespace dsu;
    void build()
    {
        for(int i = 1; i <= m; ++i) if(h[u[i]] == h[v[i]])
            connect(u[i], v[i]);        
        for(int i = 1; i <= m; ++i) 
        {
            int x = find(u[i]), y = find(v[i]);
            if(x == y) continue;
            G[x].push_back(y); G[y].push_back(x);
        }
        for(int i = 1; i <= n; ++i) 
        {
            sort(G[i].begin(), G[i].end());
            G[i].erase(unique(G[i].begin(), G[i].end()), G[i].end());
            if(G[i].size() > 2) { puts("NO"); exit(0); }
        }
    }
    void dfs(int u, int last)
    {
        used[color[u]] = 1; vis[u] = 1;
        for(int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i]; if(v == last) continue;
            if(vis[v]) { puts("NO"); exit(0); }
            if(!used[color[u] - 1]) color[v] = color[u] - 1;
            else color[v] = color[u] + 1; 
            used[color[v]] = 1;
            dfs(v, u);
        }
    }
    int main()
    {
        len = fread(CH, 1, MaxCH, stdin);
        CH[len] = ' ';
        n = read(); m = read();
        Hash[0] = 1; for(int i = 1; i <= n; ++i) Hash[i] = Hash[i - 1] * 123333, fa[i] = i, h[i] = Hash[i];
        for(int i = 1; i <= m; ++i)
        {
            u[i] = read(); v[i] = read();
            h[u[i]] += Hash[v[i]]; h[v[i]] += Hash[u[i]];
        } 
        build();
        color[find(1)] = 300000;
        dfs(find(1), 0);
        puts("YES");
        for(int i = 1; i <= n; ++i) printf("%d ", color[find(i)]);
        return 0;
    }
    View Code

    E:我们可以知道假设我们二分答案x,把>=x的数标为1,<x的数标为0,那么第一个人就是想要剩下的一个数为1,第二个人反之。那么我们可以知道两个性质:

    1.如果n为奇数,那么当且仅当中间的数等于1和他任意相邻的两个数其中为1的情况下第一个人能赢,也就是说x能取到

    2.如果n为偶数,那么当且仅当中间的两个数都为1第一个人才能赢,也就是说x能取到

    然后我们发现,既然对于任意一个x根据n必须满足上面的条件才能赢,那么也就是说答案只跟中间的几个数有关,因为一个答案必须满足使中间的数满足条件才可以

    所以我们就有答案

    n为奇数ans=min(a[t],max(a[t-1],a[t+1]))t=(n+1)/2,因为我们可以保住中间的数和两边的数之一,我们不能自己选择保哪个,只可意会不可言传,自己手画画就可以了。

    n为偶数ans=max(a[t],a[t+1])t=n/2,保哪个数可以自己选择,手画一下就可以了。

    对于取了k个我们只需要看每段连续n-k个元素的最大值就好了

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 300010;
    int n;
    int a[N], b[N], c[N], ans[N];
    struct seg {
        int tree[N << 2];
        void build(int l, int r, int x, int *a)
        {
            if(l == r) { tree[x] = a[l]; return; }
            int mid = (l + r) >> 1;
            build(l, mid, x << 1, a); build(mid + 1, r, x << 1 | 1, a);
            tree[x] = max(tree[x << 1], tree[x << 1 | 1]);
        }
        int query(int l, int r, int x, int a, int b)
        {
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return tree[x];
            int mid = (l + r) >> 1;
            return max(query(l, mid, x << 1, a, b), query(mid + 1, r, x << 1 | 1, a, b));
        }
    } t1, t2;
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for(int i = 1; i <= n; ++i)
        {
            ans[n - 1] = max(ans[n - 1], a[i]);
            b[i] = min(a[i], max(a[i - 1], a[i + 1]));
            c[i] = max(a[i], a[i + 1]);
        }
        t1.build(1, n, 1, b); t2.build(1, n, 1, c);
        int l1, r1, l2, r2;
        if(n % 2 == 0) 
        {  l1 = n / 2; r1 = l1 + 1; l2 = r2 = n / 2; }
        else { l1 = r1 = (n + 1) / 2; l2 = n / 2; r2 = l2 + 1; }    
        for(int k = 0; k < n - 1; ++k)
            if((n - k) % 2 == 1) ans[k] = t1.query(1, n, 1, l1--, r1++);
            else ans[k] = t2.query(1, n, 1, l2--, r2++);
        for(int i = 0; i < n; ++i) printf("%d ", ans[i]);
        return 0;
    }
    View Code

    F:线段树维护每位,调了好长时间,原因是要在程序顶端先pushdown一下,我没有这个习惯

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 200010;
    struct data {
        ll cnt[20];
        int nxt[20];
    } tree[N << 2];
    int n, q;
    int a[N];
    ll bin[20];
    void pushdown(int x)
    {
        static ll cnt[10]; static int nxt1[10], nxt2[10];
        memset(cnt, 0, sizeof(cnt)); 
        memset(nxt1, 0, sizeof(nxt1));
        memset(nxt2, 0, sizeof(nxt2));
        for(int i = 0; i <= 9; ++i) 
        {
            nxt1[i] = tree[x].nxt[tree[x << 1].nxt[i]];
            nxt2[i] = tree[x].nxt[tree[x << 1 | 1].nxt[i]];        
        }
        for(int i = 0; i <= 9; ++i) 
        {
            tree[x << 1].nxt[i] = nxt1[i]; 
            tree[x << 1 | 1].nxt[i] = nxt2[i]; 
        }
        for(int i = 0; i <= 9; ++i) cnt[tree[x].nxt[i]] += tree[x].cnt[i];
        for(int i = 0; i <= 9; ++i) 
        {
            tree[x].cnt[i] = cnt[i];
            tree[x].nxt[i] = i;
        } 
    }
    void build(int l, int r, int x)
    {
        if(l == r)
        {
            int t = a[l], pos = -1;
            while(t) 
            {
                tree[x].cnt[t % 10] += bin[++pos];
                t /= 10; 
            }
            for(int i = 0; i <= 9; ++i) tree[x].nxt[i] = i;
            return;
        }
        int mid = (l + r) >> 1;
        build(l, mid, x << 1); build(mid + 1, r, x << 1 | 1);    
        for(int i = 0; i <= 9; ++i) tree[x].cnt[i] = tree[x << 1].cnt[i] + tree[x << 1 | 1].cnt[i];
        for(int i = 0; i <= 9; ++i) tree[x].nxt[i] = i;
    }
    void update(int l, int r, int x, int a, int b, int x1, int y1)
    {
        pushdown(x);
        if(l > b || r < a) return;
        if(l >= a && r <= b)
        {
            tree[x].nxt[x1] = y1;
            pushdown(x);
            return;
        }
        int mid = (l + r) >> 1;
        update(l, mid, x << 1, a, b, x1, y1); update(mid + 1, r, x << 1 | 1, a, b, x1, y1);
        for(int i = 0; i <= 9; ++i) tree[x].cnt[i] = tree[x << 1].cnt[i] + tree[x << 1 | 1].cnt[i]; 
    }
    ll query(int l, int r, int x, int a, int b)
    {    
        pushdown(x);
        if(l > b || r < a) return 0;
        if(l >= a && r <= b) 
        {        
            ll ans = 0;
            for(int i = 0; i <= 9; ++i) ans += (ll)i * tree[x].cnt[i];
            return ans;
        }
        int mid = (l + r) >> 1; ll x1, x2;
        pushdown(x);
        x1 = query(l, mid, x << 1, a, b); x2 = query(mid + 1, r, x << 1 | 1, a, b);
        return x1 + x2;
    }
    int main()
    {
        scanf("%d%d", &n, &q);
        bin[0] = 1; for(int i = 1; i <= 16; ++i) bin[i] = bin[i - 1] * 10;
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        build(1, n, 1);
        while(q--)
        {
            int opt, l, r, x, y;
            scanf("%d", &opt);
            if(opt == 1)
            {
                scanf("%d%d%d%d", &l, &r, &x, &y);
                update(1, n, 1, l, r, x, y);
            }
            if(opt == 2)
            {
                scanf("%d%d", &l, &r);
                ll ans = query(1, n, 1, l, r);
                printf("%lld
    ", ans); 
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    华为面试
    多线程下的单例模式
    乐观锁的一种实现方式——CAS
    乐观锁和悲观锁
    数据库行锁,表锁
    常用的设计模式
    grunt-contrib-watch 实时监测文件状态
    grunt-contrib-compass 编译sass
    grunt的安装及使用
    dede 调取二级三级菜单栏目
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6858200.html
Copyright © 2011-2022 走看看