zoukankan      html  css  js  c++  java
  • [HDU 4666]Hyperspace[最远曼哈顿距离][STL]

    题意:

    许多 k 维点, 求这些点之间的最远曼哈顿距离. 并且有 q 次操作, 插入一个点或者删除一个点. 每次操作之后均输出结果.

    思路:

    用"疑似绝对值"的思想, 维护每种状态下各点的计算值, 插入或删除一个点就更新一次每种状态(用 multiset 或 map 或 priority_queue 实现), 每次求ans时扫一遍最大差值即可.


    为了练习STL, 每一个都实现一次.


    multiset

    /* **********************************************
    Author      : kuangbin
    Created Time: 2013/8/13 18:25:38
    File Name   : F:2013ACM练习2013多校71001.cpp
    *********************************************** */
    //4640MS    14972K
    #include <cstdio>
    #include <algorithm>
    #include <set>
    using namespace std;
    int a[60010][10];
    multiset<int>mst[1<<5];
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int q,k;
        while(scanf("%d%d",&q,&k)==2)
        {
            for(int i = 0;i < (1<<k);i++)
                mst[i].clear();
            int od,x;
            for(int i = 1;i <= q;i++)
            {
                scanf("%d",&od);
                if(od == 0)
                {
                    for(int j = 0;j < k;j++)
                        scanf("%d",&a[i][j]);
                    for(int j = 0; j < (1<<k); j++)
                    {//计算当前点在每种情况下的"疑似绝对值"
                        int s = 0;
                        for(int t = 0; t < k;t++)
                            if(j & (1<<t))
                                s += a[i][t];
                            else s -= a[i][t];
                        mst[j].insert(s);//插入到该种情况下
                    }
                }
                else
                {
                    scanf("%d",&x);
                    for(int j = 0; j < (1<<k); j++)
                    {//一次操作,插入或删除一个点,都是将这个点对应的所有状态插入每种状态中
                        int s = 0;//因此,要清除一次操作,就要删除所有状态中的那一个
                        for(int t = 0; t < k;t++)
                            if(j & (1<<t))
                                s += a[x][t];
                            else s -= a[x][t];
                        multiset<int>::iterator it = mst[j].find(s);
                        mst[j].erase(it);
                    }
                }
                int ans = 0;
                for(int j = 0; j < (1<<k);j++)
                {
                    multiset<int>::iterator it = mst[j].end();
                    it--;
                    int t1 = (*it);
                    it = mst[j].begin();
                    int t2 = (*it);//用于作差
                    ans = max(ans,t1-t2);//保留最大值
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
    

    map

    //8359MS	37928K慢死了
    
    #include <cstdio>
    #include <algorithm>
    #include <map>
    using namespace std;
    
    int a[60010][6];
    map<int, int> mp[1<<5];
    
    int main()
    {
        int q,k;
        while(scanf("%d %d",&q,&k)==2)
        {
            for(int i=0;i<1<<k;i++)
                mp[i].clear();
            int od, x;
            for(int i=1;i<=q;i++)
            {
                scanf("%d",&od);
                if(!od)
                {
                    for(int j=0;j<k;j++)
                        scanf("%d",a[i]+j);
                    for(int s=0;s<1<<k;s++)
                    {
                        int t = 0;
                        for(int j=0;j<k;j++)
                        {
                            if(s & (1<<j))  t += a[i][j];
                            else t -= a[i][j];
                        }
                        mp[s][t]++;
                      //  printf("map[s][t] = %d
    ",mp[s][t]);
                    }
                }
                else
                {
                    scanf("%d",&x);
                    for(int s=0;s<1<<k;s++)
                    {
                        int t = 0;
                        for(int j=0;j<k;j++)
                        {
                            if(s & (1<<j))  t += a[x][j];
                            else t -= a[x][j];
                        }
                        map<int, int>::iterator it = mp[s].find(t);
                        mp[s][t]--;
                    }
                }
                int ans = 0;
                for(int s=0;s<(1<<k);s++)
                {
                    map<int, int>::iterator it = mp[s].end();
                    it--;
                    while(it->second==0)   it--;
                    int mx = it->first;///first~~~
                    it = mp[s].begin();
                    while(it->second==0)   it++;
                    int mi = it->first;
                    ans = max(ans, mx - mi);
                   // printf("mx = %d, mi = %d
    ",mx,mi);
                }
                printf("%d
    ",ans);
            }
        }
    }
    

    priority_queue

    优先队列只能返回队首元素,因此需要两个队列分别求最大最小值.

    对于已删除的元素, 无法直接删除, 可以做标记, 碰到已删除的元素时直接pop掉就行了.

    因此入队的就不能仅仅是一个值(前两个有find功能, 不需要额外标号), 而应该是一个记录key和value的结构体.

    //2218MS	36748K
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    int a[6];
    bool vis[60005];
    typedef struct ascending_node
    {
        int id,t;
        bool operator<(const ascending_node& a) const
        {
            return t > a.t;
        }
    }anode;
    typedef struct descending_node
    {
        int id,t;
        bool operator<(const descending_node& a) const
        {
            return t < a.t;
        }
    }dnode;
    /*  2812MS	  30224K
    priority_queue<anode> apq[1<<5];
    priority_queue<dnode> dpq[1<<5];
    int main()
    {
        int q,k;
        while(scanf("%d %d",&q,&k)==2)
        {
            for(int i=0;i<1<<k;i++)
            {
                while(!apq[i].empty())  apq[i].pop();
                while(!dpq[i].empty())  dpq[i].pop();
            }*/
    /**/
    int main()
    {
        int q,k;
        while(scanf("%d %d",&q,&k)==2)
        {
            priority_queue<anode> apq[1<<5];
            priority_queue<dnode> dpq[1<<5];/**/
            anode t1;
            dnode t2;
            memset(vis,false,sizeof(vis));
            int od, x;
            for(int i=1;i<=q;i++)
            {
                scanf("%d",&od);
                if(!od)
                {
                    for(int j=0;j<k;j++)
                        scanf("%d",a+j);
                    for(int s=0;s<1<<k;s++)
                    {
                        int t = 0;
                        for(int j=0;j<k;j++)
                        {
                            if(s & (1<<j))  t += a[j];
                            else t -= a[j];
                        }
                        t1.t = t2.t = t;
                        t1.id = t2.id = i;
                        apq[s].push(t1);
                        dpq[s].push(t2);
                      //  printf("map[s][t] = %d
    ",mp[s][t]);
                    }
                }
                else
                {
                    scanf("%d",&x);
                    vis[x] = true;
                }
                int ans = 0;
                for(int s=0;s<(1<<k);s++)
                {
                    while(1)
                    {
                        t1 = apq[s].top();
                        if(!vis[t1.id]) break;
                        apq[s].pop();
                    }
                    while(1)
                    {
                        t2 = dpq[s].top();
                        if(!vis[t2.id]) break;
                        dpq[s].pop();
                    }
                    ans = max(ans, t2.t-t1.t);
                }
                printf("%d
    ",ans);
            }
        }
    }
    


  • 相关阅读:
    arcgis 图幅结合图表工具
    Geoprocessor clip
    Spring Boot总结,核心功能,优缺点
    代码下载python 简体和繁体的转换
    电话错误fmxl Missing handler script
    nullnull使用ps绘制像word里面的箭头
    nullnulljava把过滤掉的 % 号拿回来
    问题总结两天来两场实习面试(中科创达、华为)
    模板拷贝【便利贴】Struts性能优化
    匹配优先级Spring攻略学习笔记(3.04)指定Aspect优先级
  • 原文地址:https://www.cnblogs.com/james1207/p/3293807.html
Copyright © 2011-2022 走看看