题意:
许多 k 维点, 求这些点之间的最远曼哈顿距离. 并且有 q 次操作, 插入一个点或者删除一个点. 每次操作之后均输出结果.
思路:
用"疑似绝对值"的思想, 维护每种状态下各点的计算值, 插入或删除一个点就更新一次每种状态(用 multiset 或 map 或 priority_queue 实现), 每次求ans时扫一遍最大差值即可.
为了练习STL, 每一个都实现一次.
multiset
- /* **********************************************
- Author : kuangbin
- Created Time: 2013/8/13 18:25:38
- File 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
- //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\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的结构体.
- //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\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);
- }
- }
- }