• Full_of_Boys训练3总结


    题目来源: 2016-2017 ACM-ICPC Pacific Northwest Regional Contest

    E.Enclosure

    先计算出内外两个凸包,枚举大凸包上的点,在小凸包上找到两个切点。计算面积时,就相当于删掉几条原先的边,加上一个新的三角形。同时,可以注意到,如果我们按照顺时针枚举大凸包上的点,那两个切点也只可能朝顺时针方向移动,这样的话,就可以在线性时间内计算出新的切点了。以后补代码。

    G.Maximum Islands

    贪心方法:把原本的L四个方向的C改成W,然后剩余的C,可以运用最小割的思想,用有效点数减最小割,就是最大的答案。思想来自骑士共存。二分图用的匈牙利算法。

    #include <bits/stdc++.h>
    #define rg register
    #define pb(x) push_back(x)
    typedef long long ll;
    inline int read() {
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    inline write(int x) {
        if(x>=10) write(x/10);
        putchar('0'+x%10);
    }
    using namespace std;
    int n, m, col[45][45], dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}, vis[44][44];
    char s[45][45];
    vector<int> v[2];
    struct node{
        int x, y;
        node(){} node(int a,int b) {x = a; y = b;}
    };
    inline int inb(int x, int y) {
        if(x < 1 || x > n || y < 1 || y > m) return 0;
        return 1;
    }
    inline void bfs1(int sx, int sy) {
        queue<node> q;
        q.push(node(sx, sy));
        col[sx][sy] = 0;
        v[0].pb((sx-1)*m+sy);
        while(!q.empty()) {
            node t = q.front(); q.pop();
            for(rg int i = 0; i < 4; ++i){
                int tx = t.x + dx[i], ty = t.y + dy[i];
                if(inb(tx, ty) && s[tx][ty] == 'C' && col[tx][ty] == -1) {
                    col[tx][ty] = col[t.x][t.y]^1;
                    v[col[tx][ty]].pb((tx-1)*m+ty);
                    q.push(node(tx, ty));
                }
            }
        }
    }
    struct edge{int e, nxt;}E[55*55*4];
    int h[55*55], cc;
    inline void add(int u, int v) {
        E[cc].e = v; E[cc]. nxt = h[u]; h[u] = cc; ++cc;
    }
    inline void build() {
        memset(h, -1, sizeof(h)); cc = 0;
        for(rg int i = 1; i <= n; ++i)
            for(rg int j = 1; j <= m; ++j) if(col[i][j] == 0){
                for(rg int k = 0; k < 4; ++k) {
                    int tx = i + dx[k], ty = j + dy[k];
                    if(inb(tx, ty) && col[tx][ty] == 1) add((i-1)*m+j, (tx-1)*m+ty);
                }
            }
    }
    inline int bfs2(int sx, int sy, char c) {
        int ans = 1;
        vis[sx][sy] = 1;
        queue<node> q;
        q.push(node(sx, sy));
        while(!q.empty()) {
            node t = q.front(); q.pop();
            for(rg int i = 0; i < 4; ++i) {
                int tx = t.x + dx[i], ty = t.y + dy[i];
                if(inb(tx, ty) && s[tx][ty] == c && !vis[tx][ty]) vis[tx][ty]=1,++ans,q.push(node(tx,ty));
            }
        }
        return ans;
    }
    int used[55*55], lk[55*55];
    inline int dfs(int u) {
        for(rg int i = h[u]; ~i; i = E[i].nxt) if(!used[E[i].e]) {
            used[E[i].e] = 1;
            if(lk[E[i].e] == -1 || dfs(lk[E[i].e])) {
                lk[E[i].e] = u;
                return 1;
            }
        }
        return 0;
    }
    inline int hungray() {
        int ans = 0;
        memset(lk, -1, sizeof(lk));
        for(rg int i = 1; i <= n; ++i)
            for(rg int j = 1; j <= m; ++j) if(col[i][j] == 0){
            memset(used, 0, sizeof(used));
            if(dfs((i-1)*m+j)) ++ans;
        }
        return ans;
    }
    inline int solve() {
        int ans = 0, t = 0;
        for(rg int i = 1; i <= n; ++i)
            for(rg int j = 1; j<= m; ++j) if(s[i][j] == 'L' && !vis[i][j]) bfs2(i, j, 'L'), ++ans;
        memset(vis, 0 , sizeof(vis));
        for(rg int i = 1; i <= n; ++i)
            for(rg int j = 1; j<= m; ++j) if(s[i][j] == 'C' && !vis[i][j]) t += bfs2(i, j, 'C');
        return ans + t - hungray();
    }
    int main() {
        n=read(),m=read();
        memset(col, -1, sizeof(col));
        for(rg int i = 1; i <= n; ++i) scanf(" %s",s[i]+1);
        for(rg int i = 1; i <= n; ++i)
            for(rg int j = 1; j <= m; ++j) if(s[i][j]=='L') {
                for(rg int k = 0; k < 4; ++k) if(inb(i+dx[k],j+dy[k])&&s[i+dx[k]][j+dy[k]]=='C') {
                    s[i+dx[k]][j+dy[k]] = 'W';
                }
            }
        for(rg int i = 1; i <= n; ++i)
            for(rg int j = 1; j <= m; ++j) if(s[i][j] == 'C'&&col[i][j] == -1) {
                bfs1(i, j);
            }
        build();
        write(solve());
        return 0;
    }

    J.Shopping

    每次找到区间内最左边的小于x的数,然后%一下它,重复以上操作就行了。所以只需要实现一个区间询问最左边的小于x的值就可以了。可以证明每次操作最多log次

    解法1:分块。块外暴力,块内提前排好序二分。写挫了莫名t。

    解法2:线段树。维护一下区间最小值,显然如果左边的最小值小于等于x那就朝左边递归,否则右边,便可以完成这个操作。

    解法3:st表。又不用修改。st表干掉一个log

    code:

    解法1:挫了不贴了。

    解法2:

    #include <cstdio>
    #include <algorithm>
    #define pb(x) push_back(x)
    #define rg register
    const int maxn = 2e5 + 100;
    typedef unsigned long long ll;
    inline int readint(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    inline ll readll(){
        char c=getchar();ll x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    inline void write(ll x){
        if(x>=10LL) write(x/10LL);
        putchar('0'+x%10LL);
    }
    using namespace std;
    int n, q;
    ll a[maxn];
    struct seg{int l, r; ll x;} tr[maxn << 2];
    inline void build(int p, int l, int r) {
        tr[p].l = l; tr[p].r = r;
        if(l == r){
            tr[p].x = a[l]; return;
        }
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid+1, r);
        tr[p].x = min(tr[p<<1].x, tr[p<<1|1].x);
    }
    inline ll ask_mn(int p, int l, int r) {
        if(tr[p].l == l && tr[p].r == r) return tr[p].x;
        int mid = (tr[p].l + tr[p].r) >> 1;
        if(r <= mid) return ask_mn(p<<1, l, r);
        else if(l > mid) return ask_mn(p<<1|1, l, r);
        else return min(ask_mn(p<<1, l, mid), ask_mn(p<<1|1, mid+1, r));
    }
    inline ll fd(ll x, int L, int R) {
        if(L == R) return L;
        int mid =(L + R) >> 1;
        if(ask_mn(1, L, mid) <= x) return fd(x, L, mid);
        else return fd(x, mid+1, R);
    }
    inline ll solve(ll x, int L, int R){
        while(ask_mn(1, L, R) <= x) x %= a[fd(x, L, R)];
        return x;
    }
    int main() {
        n = readint(), q = readint();
        for(int i = 1; i <= n; ++i) a[i] = readll();
        build(1, 1, n);
        while(q--) { ll x; int L, R;
            x = readll(), L = readint(), R = readint();
            write(solve(x, L, R)); puts("");
        }
        return 0;
    }
    

    解法3:

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #define pb(x) push_back(x)
    #define rg register
    const int maxn = 2e5 + 100;
    typedef unsigned long long ll;
    inline int readint(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    inline ll readll(){
        char c=getchar();ll x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    inline void write(ll x){
        if(x>=10LL) write(x/10LL);
        putchar('0'+x%10LL);
    }
    using namespace std;
    int n, q;
    ll a[maxn], st[maxn][25];
    inline void RMQ_init(){
        for(int i = 0; i <= n; ++i) st[i][0] = a[i];
        for(int j = 1; (1<<j) <= n; ++j){
            for(int i = 1; i+(1<<j)-1 <= n; ++i){
                st[i][j] = min(st[i][j-1], st[i+(1<<(j-1))][j-1]);
            }
        }
    }
    inline ll RMQ(int u, int v){
        int k = (int)(log(v-u+1.0)/log(2.0));
        return min(st[u][k], st[v-(1<<k)+1][k]);
    }
    inline ll fd(ll x, int L, int R) {
        if(L == R) return L;
        int mid =(L + R) >> 1;
        if(RMQ(L, mid) <= x) return fd(x, L, mid);
        else return fd(x, mid+1, R);
    }
    inline ll solve(ll x, int L, int R){
        while(RMQ(L, R) <= x) x %= a[fd(x, L, R)];
        return x;
    }
    int main() {
        n = readint(), q = readint();
        for(int i = 1; i <= n; ++i) a[i] = readll();
        RMQ_init();
        while(q--) { ll x; int L, R;
            x = readll(), L = readint(), R = readint();
            write(solve(x, L, R)); puts("");
        }
        return 0;
    }
    

      

  • 相关阅读:
    window XP下 php5.5+mysql+apache2+phpmyadmin安装
    poj2478Farey Sequence
    poj2723Get Luffy Out
    niop2015day2
    P2473 [SCOI2008]奖励关
    P4284 [SHOI2014]概率充电器
    P2486 [SDOI2011]染色
    noip2015day1
    hdu 2795 Billboard
    exgcd
  • 原文地址:https://www.cnblogs.com/RRRR-wys/p/8972815.html
Copyright © 2020-2023  润新知