• HDU 2419 Boring Game(并查集+map)


    感觉做得有点复杂了,但是AC了还是。。。爽。。。

    题意:给你n个点每个点有一个价值,接下来有m条边,然后是q个操作,每个操作有三种情况:

    F X K:寻找与X点直接或间接相连的不小于价值K的最小价值,如果找不到就是0

    U X K:将X点价值变为K

    E A B:删除点A与点B形成的边

    最后求价值总和的平均值

    首先我们看F操作和U操作可以使用map解决,因为这是典型的带修改并区间找寻大于等于某值的最小值。然后我们看删边,如果直接删的话,我们需要遍历这一维map然后拆分,时间过不了。因此我们想到使用离线操作倒序添边,然后处理集合合并问题就是并查集的典型题了。

    接着我们离线后要把每个E与U都处理后再添边,对于U我们必须保存所有修改的历史,因此使用vector。而m条边中删除E的边,我们需要节约时间。存下总所有边与需要删除的边,然后一起排序后双指针维护添边(因为需要删除的边一定在所有边中出现过,且没有重边)。接着对于维护E,添边后需要把一个父节点并上去,且两个map也要合并,因此我们为了节约合并时间,需要简单的启发式合并。其实就是并查集合并时把个数少的并到个数多的上面。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<stdlib.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define eps 1E-8
    /*注意可能会有输出-0.000*/
    #define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
    #define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
    #define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
    #define mul(a,b) (a<<b)
    #define dir(a,b) (a>>b)
    typedef long long ll;
    typedef unsigned long long ull;
    const int Inf=1<<28;
    const double Pi=acos(-1.0);
    const int Mod=1e9+7;
    const int Max=300010;
    struct node
    {
        char typ[2];
        int u,v;
    }add[Max],del[Max],ope[Max];
    int fat[Max],ran[Max];//离线添边的并查集
    map<int,int> mp[Max];//祖先形成的集合里的元素
    vector<int> vec[Max];//存下修改的过程值
    int len[Max];
    void Init(int n)
    {
        for(int i=0;i<n;++i)
        {
            ran[i]=1;
            len[i]=0;
            vec[i].clear();
            mp[i].clear();
            fat[i]=i;
        }
        return;
    }
    int Find(int x)
    {
        if(x==fat[x])
            return fat[x];
        return fat[x]=Find(fat[x]);
    }
    void UnMap(int x1,int y1)
    {
        for(map<int,int>::iterator it=mp[x1].begin();it!=mp[x1].end();)
        {
        if(!mp[y1].count(it->first))
            mp[y1][it->first]=it->second;
        else
            mp[y1][it->first]+=it->second;
        mp[x1].erase(it++);//删除
        }
        return;
    }
    void Union(int x,int y)
    {
        int x1=Find(x);
        int y1=Find(y);
        if(x1==y1)
            return;
            if(ran[x1]<ran[y1])
            {
                fat[x1]=y1;//价值合并
                ran[y1]+=ran[x1];
        UnMap(x1,y1);
            }
        else
        {
            fat[y1]=x1;//价值合并
            ran[x1]+=ran[y1];
        UnMap(y1,x1);
        }
        return;
    }
    bool cmp(struct node p1,struct node p2)
    {
        if(p1.u==p2.u)
            return p1.v<p2.v;
        return p1.u<p2.u;
    }
    map<int,int>::iterator it;
    double Solve(int n,int m,int q,int cnt,int dig)
    {
        int coun=0;
        double ans=0.0;
        for(int i=0;i<n;++i)
            mp[i][vec[i][len[i]]]=1;//开始每个集合是自己
            sort(add,add+m,cmp);
            sort(del,del+cnt,cmp);
            del[cnt].u=del[cnt].v=-1;
            //for(int i=0;i<m;++i)
            //    printf("%d %d
    ",add[i].u,add[i].v);
             //   printf("OK
    ");
           // for(int i=0;i<cnt;++i)
                //printf("%d %d
    ",del[i].u,del[i].v);
        for(int i=0;i<m;++i)//初始添边
        {
            if(add[i].u==del[coun].u&&add[i].v==del[coun].v)//两边排序后双指针维护
                coun++;
        else
        {//printf("OK
    ");
             Union(add[i].u,add[i].v);
        }
        }
        for(int i=q-1;i>=0;--i)
        {
            if(ope[i].typ[0]=='F')
            {
                int x1=Find(ope[i].u);
                it=mp[x1].lower_bound(ope[i].v);
                if(it==mp[x1].end())
                    ans+=0.0;
                else
                    ans+=it->first;
            }
            else if(ope[i].typ[0]=='E')
               Union(ope[i].u,ope[i].v);
            else//换价值
            {
                int x1=Find(ope[i].u);
                mp[x1][ope[i].v]--;
                if(mp[x1][ope[i].v]==0)
                    mp[x1].erase(ope[i].v);
                    if(mp[x1].count(vec[ope[i].u][len[ope[i].u]-1]))
                mp[x1][vec[ope[i].u][--len[ope[i].u]]]++;
                else
                     mp[x1][vec[ope[i].u][--len[ope[i].u]]]=1;
            }
        }//printf("%d
    ",dig);
        return ans/dig;
    }
    int main()
    {
        int n,m,q;
        int u,v,c;
        int cnt,dig,coun=0;
        while(~scanf("%d %d %d",&n,&m,&q))
        {
            Init(n);
            dig=cnt=0;
            for(int i=0;i<n;++i)
            {
                scanf("%d",&c);
                vec[i].push_back(c);
            }
            for(int i=0;i<m;++i)
            {
                scanf("%d %d",&u,&v);
                u--,v--;
                if(u>v)
                    swap(u,v);
                add[i].u=u;
                add[i].v=v;
            }
            for(int i=0;i<q;++i)
            {
                scanf("%s %d %d",&ope[i].typ,&ope[i].u,&ope[i].v);
                if(ope[i].typ[0]=='F')
                {
                    dig++;
                ope[i].u--;
                }
                else if(ope[i].typ[0]=='E')
                {
                ope[i].u--,ope[i].v--;
                if(ope[i].u>ope[i].v)
                    swap(ope[i].u,ope[i].v);
                del[cnt].u=ope[i].u,del[cnt++].v=ope[i].v;
                }
                else
                {
                ope[i].u--;
                len[ope[i].u]++;
                vec[ope[i].u].push_back(ope[i].v);
                }
            }
            printf("Case %d: %.3f
    ",++coun,Solve(n,m,q,cnt,dig));
            Init(n);
        }
        return 0;
    }
  • 相关阅读:
    Silverlight与WPF开发人员入门应该知道的十件事
    Silverlight4.0教程之使用鼠标右键事件和滚轮事件
    Silverlight实用窍门系列:4.Silverlight 4.0添加鼠标右键菜单和Silverlight全屏模式的进入退出。【附带源码实例】
    将moss 2007的模板文件导入到moss 2010
    Silverlight4.0教程之打印报表和图形
    .NET MessageBox 网页弹出消息框
    使用sharepoint自带的文本编辑器1
    C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):目录
    推荐一个非常好的在线免费的 Photoshop
    Silverlight游戏设计(Game Design):目录
  • 原文地址:https://www.cnblogs.com/zhuanzhuruyi/p/5894750.html
Copyright © 2020-2023  润新知