UESTC 数据结构专题训练 K,L,M

来源:互联网 发布:autocad机械制图软件 编辑:程序博客网 时间:2024/05/22 00:10

K:http://acm.uestc.edu.cn/#/problem/show/1593


解法:直接并查集加SET维护即可。


#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 100010;int a[maxn], id[maxn], fa[maxn];LL sum[maxn],ans[maxn];set<LL>s;bool vis[maxn];int n;int find_set(int x){    if(x==fa[x]) return fa[x];    else return fa[x]=find_set(fa[x]);}void union_set(int x, int y){    int fx=find_set(x),fy=find_set(y);    if(fx!=fy){        fa[fx]=fy;        sum[fy]+=sum[fx];    }}int main(){    while(~scanf("%d",&n)){        for(int i=1; i<=n; i++) scanf("%d", &a[i]);        for(int i=1; i<=n; i++) scanf("%d", &id[i]);        for(int i=0; i<=n; i++) fa[i]=i,sum[i]=a[i],vis[i]=0,ans[i]=0;        s.clear();        for(int i=n; i>=1; i--){            if(s.empty()) ans[i]=0;            else            {                auto it = s.end();                it--;                ans[i]=*it;            }            if(vis[id[i]-1]){                s.erase(sum[find_set(id[i]-1)]);                union_set(id[i]-1,id[i]);                s.insert(sum[find_set(id[i]-1)]);                vis[id[i]]=1;            }            if(vis[id[i]+1]){                s.erase(sum[find_set(id[i]+1)]);                union_set(id[i]+1,id[i]);                s.insert(sum[find_set(id[i]+1)]);                vis[id[i]]=1;            }            if(!vis[id[i]-1]&&!vis[id[i]+1]){                s.insert(sum[id[i]]);                vis[id[i]]=1;            }        }        for(int i=1; i<=n; i++) printf("%lld\n", ans[i]);    }    return 0;}

L:http://acm.uestc.edu.cn/#/problem/show/1594


解法:POJ的食物链,带权并查集维护,见这里 http://blog.csdn.net/just_sort/article/details/59547406


#include <bits/stdc++.h>using namespace std;const int maxn = 1000100;int N, K, relation, a, b, cnt;int p[maxn], r[maxn];//p代表x的父亲,r代表x和fa[x]的关系0, 1, 2分别代表同类,***int ans[1000010];void init(){    for(int i = 1; i <= N; i++)    {        p[i] = i;        r[i] = 0;    }}int find_set(int x){    int temp = p[x];    if(x == p[x]) return p[x];    p[x] = find_set(p[x]);    r[x] = (r[x] + r[temp]) % 3;    return p[x];}void union_set(int x, int y, int px, int py){    p[px] = py;    r[px] = (r[y] - r[x] + 3 + relation - 1) % 3;}int main(){    while(~scanf("%d%d", &N, &K))    {        cnt = 0;        init();        int tot = 0;        memset(ans,0,sizeof(ans));        while(K--)        {            ++tot;            scanf("%d%d%d", &relation, &a, &b);            int pa, pb;            pa = find_set(a);            pb = find_set(b);            if(a > N || b > N || (relation == 2 && a == b))            {                ++cnt;                ans[cnt]=tot;                continue;            }            if(pa != pb)            {                union_set(a, b, pa, pb);                continue;            }            if((r[a] - r[b] + 3) % 3 != (relation - 1))            {                ++cnt;                ans[cnt]=tot;                continue;            }        }        for(int i=1; i<=cnt; i++) printf("%d ", ans[i]);        puts("");    }    return 0;}

L:http://acm.uestc.edu.cn/#/problem/show/1595


解法:

他每次毒奶就会当前能力*2或*2+1,就意味着被毒奶之前能力值是⌊x/2⌋
你需要让最大值最小,并且不存在重复的值,就贪心每次选取最大的人的能力值,把他压缩为 可行的最大的x/(2^k)

#include <bits/stdc++.h>using namespace std;map<int,bool>vis;priority_queue<int>q;int a[50010];int main(){    int n;    while(~scanf("%d",&n)){        while(!q.empty()) q.pop();        for(int i=1; i<=n; i++) scanf("%d", &a[i]);        vis.clear();        for(int i=1; i<=n; i++) q.push(a[i]),vis[a[i]]=1;        int ans=0;        while(!q.empty()){            int x = q.top();            vis[x]=0;            while(x){                x>>=1;                if(x&&!vis[x]){                    break;                }            }            if(x&&!vis[x]){                q.pop();                q.push(x);                vis[x]=1;            }            else{                break;            }        }        printf("%d\n", q.top());    }    return 0;}



原创粉丝点击