[HDU 4666]Hyperspace[最远曼哈顿距离][STL]

来源:互联网 发布:淘宝现货是骗局吗 编辑:程序博客网 时间:2024/04/30 01:41

题意:

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

思路:

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


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


multiset

/* **********************************************Author      : kuangbinCreated Time: 2013/8/13 18:25:38File Name   : F:\2013ACM练习\2013多校7\1001.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\n",ans);        }    }    return 0;}

map

//8359MS37928K慢死了#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\n",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\n",mx,mi);            }            printf("%d\n",ans);        }    }}

priority_queue

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

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

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

//2218MS36748K#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  30224Kpriority_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\n",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\n",ans);        }    }}


原创粉丝点击