小比赛(POJ 2992,UVALive 4108,POJ 2263,POJ 3617,HDU 5305,POJ 1988,POJ 1679,POJ 3481)

题目链接:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=89012#overview

密码:

654


1.Case of the Zeros and Ones

题目链接:

http://codeforces.com/problemset/problem/556/A

解题思路:

官方题解:

If there still exist at least one 0 and at least one 1 in the string then there obviously exists either substring 01 or substring 10 (or both) and we can remove it. The order in which we remove substrings is unimportant: in any case we will make min(#zeros, #ones) such operations. Thus the answer is #ones + #zeros - 2min(#ones, #zeros) = |#ones - #zeros|.

AC代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
using namespace std;
int main(){
    int n;
    string str;
    while(cin>>n){
        cin>>str;
        int l = str.size();
        int sum1 = 0,sum2 = 0;
        for(int i = 0; i < l; i++){
            if(str[i] == '0')
                sum1++;
            else if(str[i] == '1')
                sum2++;
        }
        cout<<abs(sum1-sum2)<<endl;
        //printf("%d\n",abs(sum1-sum2));
    }
    return 0;
}


2.Divisors

题目链接:

http://poj.org/problem?id=2992

解题思路:

http://blog.csdn.net/piaocoder/article/details/47955351

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

typedef long long ll;
vector<int> v;
int prime[500];
int a[450][450];
int unprime[500],nprime;
int sum[500];

void getprime(){
    nprime = 0;
    memset(unprime,0,sizeof(unprime));
    for(int i = 2; i < 500; i++){
        for(int j = i*i; j < 500; j+=i)
            unprime[j] = 1;
    }
    for(int i = 2; i < 500; i++){
        if(!unprime[i])
            prime[nprime++] = i;
    }
}

void div(int x){
    v.clear();
    int t = x;
    for(int i = 0; i < nprime && prime[i]*prime[i] <= x; i++){
        while(t % prime[i] == 0){
            v.push_back(prime[i]);
            t /= prime[i];
        }
        if(t == 1)
            break;
    }
    if(t > 1)
        v.push_back(t);
}

void solve(){
    memset(a,0,sizeof(a));
    for(int i = 2; i <= 431; i++){
        memcpy(a[i],a[i-1],sizeof(a[i]));
        div(i);
        for(int j = 0; j < v.size(); j++)
            a[i][v[j]]++;
    }
}

int main(){
    getprime();
    solve();
    int n,k;
    while(~scanf("%d%d",&n,&k)){
        memset(sum,0,sizeof(sum));
        for(int i = 1; i <= 431; i++)
            sum[i] += a[n][i]-a[k][i]-a[n-k][i];
        ll ans = 1;
        for(int i = 2; i <= 431; i++)
            ans *= (sum[i]+1);
        printf("%lld\n",ans);
    }
    return 0;
}


3.SKYLINE

题目链接:

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2109

解题思路:

http://blog.csdn.net/piaocoder/article/details/47958199

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 100005;
const int NN = 100000;
struct node{
    int l,r,maxn;
    int lazy;
}tree[N<<2];
int sum;

void build(int id,int l,int r){
    tree[id].l = l;
    tree[id].r = r;
    tree[id].maxn = 0;
    tree[id].lazy = 1;
    if(l == r)
        return ;
    int mid = (l+r)>>1;
    build(id<<1,l,mid);
    build(id<<1|1,mid+1,r);
}

void pushdown(int id){
    if(tree[id].lazy){
        tree[id<<1].maxn = tree[id<<1|1].maxn = tree[id].maxn;
        tree[id].lazy = 0;
    }
}

void update(int id, int l, int r, int h){
    if (tree[id].l == l && tree[id].r == r && tree[id].lazy){
        if (h > tree[id].maxn)
            tree[id].maxn = h;
        return;
    }
    pushdown(id);
    int mid = (tree[id].l+tree[id].r)>>1;
    if (r <= mid)
        update(id<<1,l,r,h);
    else if (l > mid)
        update(id<<1|1,l,r,h);
    else {
        update(id<<1,l,mid,h);
        update(id<<1|1,mid+1,r,h);
    }
    tree[id].maxn = max(tree[id<<1].maxn,tree[id<<1|1].maxn);
}

int query(int id,int l,int r,int h){
    if(tree[id].lazy){
        if(tree[id].maxn <= h){
            update(id,l,r,h);
            return r-l+1;
        }
        else
            return 0;
    }
    pushdown(id);
    int mid = (tree[id].l+tree[id].r)>>1;
    if (r <= mid)
        return query(id<<1,l,r,h);
    else if (l > mid)
        return query(id<<1|1,l,r,h);
    else
        return query(id<<1,l,mid,h) + query(id<<1|1,mid+1,r,h);
    tree[id].maxn = max(tree[id<<1].maxn,tree[id<<1|1].maxn);
}

int main(){
    int T,n;
    scanf("%d",&T);
    while(scanf("%d",&n),n){
        int ans = 0;
        build(1,1,NN);
        int l,r,h;
        for(int i = 0; i < n; i++){
            scanf("%d%d%d",&l,&r,&h);
            r--;
            sum = query(1,l,r,h);
            ans += sum;
        }
        printf("%d\n",ans);
    }
    return 0;
}


4.Heavy Cargo

题目链接:

http://poj.org/problem?id=2263

解题思路:

一开始读错了题,想成了最大流,后来才发现,原来题意是这样的。。。

有n个点,m条路,每条路双向的,现在卡车从某点到另一点,卡车的承载无上限,但是马路的承载有上限,问卡车应该承载多少才不会压坏马路。

用dijkstra和floyd都可以做,求出最小负载中的最大值。。。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#include <algorithm>
#define INF 0xfffffff
using namespace std;

const int N = 210;
int n,m;
int edge[N][N];
map<string,int> mm;
int dis[N];
int vis[N];
int minn;
string str1,str2;

void dijkstra(int cur)
{
    int i,j,next,MAX;
    memset(vis,0,sizeof(vis));
    for(i = 1; i <= n; i++)
        dis[i] = edge[cur][i];
    dis[cur] = 0;
    for(i = 1; i <= n; i++)
    {
        MAX = 0;
        for(j = 1; j <= n; j++)
            if(!vis[j] && dis[j]>MAX)
                MAX = dis[next=j];
        vis[next] = 1;
        for(j = 1; j<= n; j++)
            if(!vis[j] && dis[j] < min(MAX,edge[next][j]))
                dis[j] = min(MAX,edge[next][j]);
    }
}

void floyd(){
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                edge[i][j] = max(edge[i][j],min(edge[i][k],edge[k][j]));
            }
        }
    }
}

int main(){
    int t = 1;
    while(scanf("%d%d",&n,&m),n+m){
        mm.clear();
        memset(edge,0,sizeof(edge));
        int num;
        int id = 1;
        for(int i = 0; i < m; i++){
            cin>>str1>>str2>>num;
            if(!mm[str1])
                mm[str1] = id++;
            if(!mm[str2])
                mm[str2] = id++;
            edge[mm[str1]][mm[str2]] = edge[mm[str2]][mm[str1]] = num;
        }
        cin>>str1>>str2;
        minn = INF;
        //dijkstra(mm[str1]);
        floyd();
        printf("Scenario #%d\n",t++);
        printf("%d tons\n\n",edge[mm[str1]][mm[str2]]);
    }
    return 0;
}


5.Kyoya and Photobooks

题目链接:

http://codeforces.com/problemset/problem/554/A

解题思路:

官方题解:

Solving this problem just requires us to simulate adding every character at every position at the string, and removing any duplicates. For instance, we can use a HashSet of Strings in Java to do this (a set in C++ or Python works as well).

Bonus: Prove that the number of ways is always (length of string + 1) * 25 + 1.


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

int main(){
    string str;
    while(cin>>str){
        int l = str.size();
        printf("%d\n",25*(l+1)+1);
    }
    return 0;
}


6.Best Cow Line

题目链接:

http://poj.org/problem?id=3617

解题思路:

http://blog.csdn.net/piaocoder/article/details/47425177

AC代码:

#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <string>  
using namespace std;  
  
int main(){  
    int n;  
    while(~scanf("%d",&n)){  
        string str = "";  
        char x;  
        for(int i = 0; i < n; i++){  
            cin>>x;  
            str += x;  
        }  
        int l = 0,r = n-1;  
        int sum = 0;  
        while(l <= r){  
            bool flag;//表示是否取左边  
            for(int i = 0; l + i <= r; i++){  
                if(str[l+i] < str[r-i]){  
                    flag = true;  
                    break;  
                }  
                else if(str[l+i] > str[r-i]){  
                    flag = false;  
                    break;  
                }  
            }  
            if(flag)  
                putchar(str[l++]);  
            else  
                putchar(str[r--]);  
            sum++;  
            if(sum % 80 == 0){  
                printf("\n");  
            }  
        }  
    }  
    return 0;  
}  


7.Friends

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5305

解题思路:

http://blog.csdn.net/piaocoder/article/details/47657163

AC代码:

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
  
int n,m;  
int a[30],b[30],cnt;  
int sum[10],on[10],off[10];//sum记录每个点的度数,on记录每个点的online,off记录每个点的offline  
  
bool judge(){  
    for(int i = 1; i <= n; i++){  
        if(on[i] != off[i])  
            return false;  
    }  
    return true;  
}  
  
void dfs(int cur){  
    if(cur == m+1){  
        if(judge()){  
            cnt++;  
            return;  
        }  
    }  
    int x = a[cur], y = b[cur];  
    if(on[x] < sum[x]/2 && on[y] < sum[y]/2){  
        on[x]++;  
        on[y]++;  
        dfs(cur+1);  
        on[x]--;  
        on[y]--;  
    }  
    if(off[x] < sum[x]/2 && off[y] < sum[y]/2){  
        off[x]++;  
        off[y]++;  
        dfs(cur+1);  
        off[x]--;  
        off[y]--;  
    }  
}  
  
int main(){  
    int T;  
    scanf("%d",&T);  
    while(T--){  
        memset(on,0,sizeof(on));  
        memset(off,0,sizeof(off));  
        memset(sum,0,sizeof(sum));  
        int flag = 1;  
        cnt = 0;  
        scanf("%d%d",&n,&m);  
        for(int i = 1; i <= m; i++){  
            scanf("%d%d",&a[i],&b[i]);  
            sum[a[i]]++;  
            sum[b[i]]++;  
        }  
        for(int i = 1; i <= n; i++){  
            if(sum[i] % 2){  
                flag = 0;  
                break;  
            }  
        }  
        if(flag){  
            dfs(1);  
            printf("%d\n",cnt);  
        }  
        else  
            printf("0\n");  
    }  
    return 0;  
}  


8.Cube Stacking

题目链接:

http://poj.org/problem?id=1988

解题思路:

http://blog.csdn.net/piaocoder/article/details/47959257

AC代码:

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 30005;
int pa[N];
int dis[N];
int cnt[N];

int findset(int x){
    if(x == pa[x])
        return pa[x];
    int root = findset(pa[x]);
    dis[x] += dis[pa[x]];
    pa[x] = root;
    return pa[x];
}

int main(){
    int p;
    while(~scanf("%d",&p)){
        char op[5];
        int a,b;
        for(int i = 1; i <= N; i++){
            pa[i] = i;
            cnt[i] = 1;
            dis[i] = 0;
        }
        while(p--){
            scanf("%s",op);
            if(op[0] == 'M'){
                scanf("%d%d",&a,&b);
                a = findset(a);
                b = findset(b);
                if(a != b){
                    pa[b] = a;
                    dis[b] = cnt[a];
                    cnt[a] += cnt[b];
                }
            }
            else{
                scanf("%d",&a);
                b = findset(a);
                printf("%d\n",cnt[b]-dis[a]-1);
            }
        }
    }
    return 0;
}


9.The Unique MST

题目链接:

http://poj.org/problem?id=1679

解题思路:

http://blog.csdn.net/piaocoder/article/details/47960579

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int n,m;
struct Edge
{
    int u,v,w;
    int flag;
}edge[100005];
int pa[110];
int del[110];

bool cmp(Edge a,Edge b)
{
    return a.w < b.w;
}

void init(){
    for(int i = 1; i <= n; i++)
        pa[i] = i;
}

int findset(int x)
{
    if(pa[x] != x)
        pa[x] = findset(pa[x]);
    return pa[x];
}

int kruskal(int dell)
{
    int i,u,v,cnt = n,sum = 0;
    for(i = 0; i < m; i++)
    {
        if(i == dell)
            continue;
        u = findset(edge[i].u);
        v = findset(edge[i].v);
        if(u != v)
        {
            sum += edge[i].w;
            pa[v] = u;
            edge[i].flag = 1;
            if(--cnt == 1)
                break;
        }
    }
    return sum;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        int u,v,w;
        for(int i = 0; i < m; i++){
            scanf("%d%d%d",&u,&v,&w);
            edge[i].u = u;
            edge[i].v = v;
            edge[i].w = w;
            edge[i].flag = 0;
        }
        sort(edge,edge+m,cmp);
        int ans,ans1,tmp = 0,k = 0;
        init();
        ans = kruskal(-1);
        for(int i = 1; i <= n; i++)
            if(pa[i] == i)
                tmp++;
        if(tmp > 1){
            printf("0\n");
            continue;
        }
        for(int i = 0; i < m; i++)
            if(edge[i].flag)
                del[k++] = i;
        int flag = 0;
        for(int i = 0; i < k; i++){
            init();
            ans1 = kruskal(del[i]);
            tmp = 0;
            for(int j = 1; j <= n; j++)
                if(pa[i] == i)
                    tmp++;
            if(tmp > 1)
                continue;
            if(ans1 == ans){
                flag = 1;
                break;
            }
        }
        if(flag)
            printf("Not Unique!\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


10.Double Queue

题目链接:

http://poj.org/problem?id=3481

解题思路:

给你三种操作:

1.插入数据;

2.弹出优先级最高的数据;

3.弹出优先级最低的数据。

用set很轻松就解决了。。。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;

struct node{
    int num,p;
    bool operator < (const node &a) const{
        return p > a.p;
    }
};

set<node> s;

int main(){
    s.clear();
    int op,x,y;
    set<node>::iterator it;
    while(1){
        scanf("%d",&op);
        if(op == 0)
            break;
        else if(op == 1){
            scanf("%d%d",&x,&y);
            s.insert(node{x,y});
        }
        else if(op == 2){
            if(s.size() == 0){
                printf("0\n");
                continue;
            }
            it = s.begin();
            printf("%d\n",it->num);
            s.erase(it);
        }
        else if(op == 3){
            if(s.size() == 0){
                printf("0\n");
                continue;
            }
            it = s.end();
            it--;
            printf("%d\n",it->num);
            s.erase(it);
        }
    }
    return 0;
}


你可能感兴趣的:(小比赛(POJ 2992,UVALive 4108,POJ 2263,POJ 3617,HDU 5305,POJ 1988,POJ 1679,POJ 3481))