zoukankan      html  css  js  c++  java
  • 2012-2013 ACM-ICPC, NEERC, Central Subregional Contest

    A Hanoi Tower 递归

    题意:

    大家都很熟悉汉诺塔的递归程序,现在给你一个组合,询问你这个组合是否会出现在汉诺塔的递归过程中。

    题解:

    将汉诺塔的递归程序反过来思考,考虑当前最大的那个盘,我们只会将他从from移动到to,他上面的盘都移动到tmp,那么这个最大的盘一定不会在tmp。如果这个盘在from,说明当前正在进行的过程是将他上面的盘从from移动到tmp,如果这个盘在to,那么说明当前正在进行的过程是将他上面的盘从tmp移动到to。递归下去即可。

    代码:

    #include<string>
    #include<algorithm>
    #include<fstream>
    using namespace std;
    
    string s;
    int n;
    bool dfs(char from,char to,char tmp,int i) {
        if (i == n)return true;
        if (s[i] == tmp)return false;
        if (s[i] == from)return dfs(from, tmp, to, i + 1);
        if (s[i] == to)return dfs(tmp, to, from, i + 1);
    }
    
    int main() {
        ifstream cin("Input.txt");
        ofstream cout("Output.txt");
        cin.sync_with_stdio(false);
        cin >> n;
        cin >> s;
        reverse(s.begin(), s.end());
        if (s[0] == 'C') {
            cout << "NO" << endl;
            return 0;
        }
        if (dfs('A', 'B', 'C', 0))
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
        return 0;
    }
    View Code

    B Island 模拟

    题意:

    给你一个加减号组成的图,问你有多少加号与减号相邻。

    题解:

    直接模拟就好了。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <vector>
    #include <math.h>
    #define INF 0x3f3f3f3f
    #define pi 3.141592654
    
    using namespace std;
    
    char str[1001][1001];
    int n,m;
    
    int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
    
    bool canmove(int x,int y){
        return x >= 0 && x < n && y >= 0 && y < m;
    }
    
    int main() {
        freopen("Input.txt", "r", stdin);
        freopen("Output.txt", "w", stdout);
        while(scanf("%d %d",&n,&m) != EOF){
            for(int i=0;i<n;i++)
                scanf("%s",str[i]);
            int ans = 0;
            for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(str[i][j] == '+'){
                for(int k=0;k<4;k++){
                    int nx = i + dx[k];
                    int ny = j + dy[k];
                    if(canmove(nx,ny) && str[nx][ny] != '+'){
                            ans++;
                           // printf("%d %d
    ", i, j);
                            break;
                    }
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    C Sequence 打表找规律

    题意:

    给你一个序列生成器,定义$a[0]=1$,对于$i>0$,$a[i]=sort(a[i-1]*2)$,其中sort是按每一位排序,这个序列的前几项是1,2,4,8,16,23,46,29,58....

    现在问你第n项是多少。

    题解:

    就把序列放到OEIS上,然后就知道规律了。

    代码:

    #include<cstring>
    #include<cstdio>
    #include<fstream>
    #define MAX_N 50
    using namespace std;
    
    long long n;
    
    long long a[MAX_N]={1, 2, 4, 8, 16, 23, 46, 29, 58, 116, 223, 446, 289, 578, 1156, 1223, 2446, 2489, 4789, 5789, 11578, 12356, 12247, 24449, 48889, 77789, 155578, 111356, 122227, 244445};
    
    int main() {
        ifstream cin("Input.txt");
        ofstream cout("Output.txt");
        cin >> n;
        n--;
        if (n < 30)cout << a[n] << endl;
        else cout << a[(n % 6) + 24] << endl;
        return 0;
    }
    View Code

    H Milestones 主席树

    题意:

    给你一个序列,然后若干次询问,询问从L到R之间有多少不同的值。

    题解:

    就。。这题是队友做的,貌似就建若干棵主席树,然后搞搞。

    代码:

    #include <stdio.h>
    #include <algorithm>
    #include <cstring>
    #define maxn 10010
    
    using namespace std;
    
    int tot, a[maxn], cnt;
    
    struct N { int ls, rs, w; } tree[300 * maxn];
    int roots[maxn], las[300];
    
    int build_tree(int l, int r) {
        int newnode = tot++;
        tree[newnode].w = 0;
        if (l != r) {
            int mid = (l + r) / 2;
            tree[newnode].ls = build_tree(l, mid);
            tree[newnode].rs = build_tree(mid + 1, r);
        }
        return newnode;
    }
    
    int updata(int rt, int pos, int val) {
        int newnode = tot++, tmp = newnode;
        tree[newnode].w = tree[rt].w + val;
        int l = 1, r = cnt;
        while (l < r) {
            int mid = (l + r) / 2;
            if (pos <= mid) {
                tree[newnode].ls = tot++;
                tree[newnode].rs = tree[rt].rs;
                newnode = tree[newnode].ls;
                rt = tree[rt].ls;
                r = mid;
            }
            else {
                tree[newnode].ls = tree[rt].ls;
                tree[newnode].rs = tot++;
                newnode = tree[newnode].rs;
                rt = tree[rt].rs;
                l = mid + 1;
            }
            tree[newnode].w = tree[rt].w + val;
        }
        return tmp;
    }
    
    int query(int rt, int k) {
        int l = 1,r = cnt;
        int ans = 0;
        if(k == 0) return tree[rt].w;
        while(l < r){
            int mid = (l + r) / 2;
            if(k <= mid){
                ans += tree[tree[rt].rs].w;
                rt = tree[rt].ls;
                r = mid;
            }
            else{
                rt = tree[rt].rs;
                l = mid + 1;
            }
        }
        return ans;
    }
    
    int n, q;
    
    void print(int rt, int l = 1, int r = cnt) {  
        printf("l = %d r = %d w = %d
    ", l, r, tree[rt].w);
        if (l != r) {  
            int mid = (l + r) / 2;  
            print(tree[rt].ls, l, mid);  
            print(tree[rt].rs, mid + 1, r);  
        }  
    }  
    
    int main() {
        freopen("Input.txt", "r", stdin);
        freopen("Output.txt", "w", stdout);
        while (scanf("%d %d", &n, &q) != EOF) {
            for (int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            cnt = n;
            tot = 0;
            memset(las, -1, sizeof(las));
            roots[0] = build_tree(1, cnt);
            for (int i = 1; i <= n; i++) {
                if (las[a[i]] == -1) {
                    roots[i] = updata(roots[i - 1], i, 1);
                }
                else {
                    roots[i] = updata(roots[i - 1], las[a[i]], -1);
                    roots[i] = updata(roots[i], i, 1);
                }
                las[a[i]] = i;
            }
            int l, r;
            while (q--) {
                scanf("%d %d", &l, &r);
                printf("%d
    ", query(roots[r], l - 1));
            }
        }
        return 0;
    }
    View Code

    J Computer Network Tarjan+dp

    题意:

    给你一个图,问你加一条边,使得图的桥的数量减少到最少,输出这条边。

    题解:

    就Tarjan一发,令桥的权值是1,非桥的权值是0,在Tarjan树上寻找直径即可,整个过程可以在Tarjan的时候dp来完成。令dp[i]表示节点i到其子树的某个叶子的最长路径,然后维护每个点dp的最大和次大值,更新答案即可。

    代码:

    //#include<iostream>
    #include<fstream>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<set>
    #define MAX_N 100004
    #define MAX_M 100005
    using namespace std;
    
    int dfn[MAX_N],low[MAX_N],ind=0;
    bool vis[MAX_N];
    
    int dp[MAX_N];
    int pre[MAX_N];
    int ans = -1;
    int x,y;
    
    struct riGou {
    public:
        int u, v, id;
    
        riGou(int uu, int vv, int i) : u(uu), v(vv), id(i) { }
    
        riGou() { }
    
        bool operator<(const riGou &a) const {
            if (u == a.u)
                return v < a.v;
            return u < a.u;
        }
    };
    
    struct edge {
    public:
        int to, id;
    
        edge(int t, int i) : to(t), id(i) { }
    
        edge() { }
    };
    
    vector<edge> G[MAX_N];
    
    set<riGou> se;
    bool haSame[MAX_N];
    
    void Tarjan(int u,int p) {
        dfn[u] = low[u] = ++ind;
        vis[u] = 1;
        int a = 0, b = 0;
        int nx = u, ny = u;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].to;
            if (v == p)continue;
            if (!vis[v]) {
                Tarjan(v, u);
                low[u] = min(low[u], low[v]);
                int ib = 0;
                if (low[v] > dfn[u] && haSame[G[u][i].id] == 0)
                    ib = 1;
                if (a <= dp[v] + ib)b = a, a = dp[v] + ib, ny = nx, nx = pre[v];
                else if (b <= dp[v] + ib)b = dp[v] + ib, ny = pre[v];
            }
            else
                low[u] = min(dfn[v], low[u]);
        }
        dp[u] = a;
        pre[u] = nx;
        if (ans < a + b) {
            x = nx, y = ny;
            ans = a + b;
        }
    }
    
    int n,m;
    
    int main() {
        ifstream cin("Input.txt");
        ofstream cout("Output.txt");
        cin.sync_with_stdio(false);
        cin >> n >> m;
        for (int i = 0; i < m; i++) {
            int u, v;
            cin >> u >> v;
            riGou a(u, v, i);
            riGou b(v, u, i);
            auto it = se.find(a);
            if (it != se.end()) {
                haSame[it->id] = 1;
                continue;
            }
            it = se.find(b);
            if (it != se.end()) {
                haSame[it->id] = 1;
                continue;
            }
            G[u].push_back(edge(v, i));
            G[v].push_back(edge(u, i));
            se.insert(riGou(u, v, i));
        }
        Tarjan(1, 0);
        if (x == y)
            cout << 1 << " " << n << endl;
        else
            cout << x << " " << y << endl;
        //cout << ans << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 1739 Tony's Tour(插头DP)
    POJ 1741 Tree(树的分治)
    POJ 1655 Balancing Act(求树的重心)
    POJ 2631 Roads in the North(求树的直径,两次遍历 or 树DP)
    codeforces 359E Neatness(DFS+构造)
    codeforces 295C Greg and Friends(BFS+DP)
    codeforces 228E The Road to Berland is Paved With Good Intentions(2-SAT)
    Eclipse 代码提示功能设置。
    svn 清空
    android 线程
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4782558.html
Copyright © 2011-2022 走看看