刚开始用map做的,TLE了,之后换priority_queue,成功AC
TLE代码:(闲的没事,用stringstream花里胡哨一下 )
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <sstream>
#define LL long long
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=a;i<n;++i)
#define foo(i,a,n) for(int i=a;i<=n;++i)
const int INF = 0x3f3f3f3f;
using namespace std;
template<class T>inline void read(T &x){
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
}
map<int,int> mp;
void op(string s){
int a;
stringstream ss;
ss.clear();
ss.str(s);
ss>>a;//丢弃第一个数
while(ss>>a)//如果还有数
mp[a]++;
}
int main(){
int t;
LL sum=0;
string s;
getline(cin,s);
stringstream ss;
ss.clear();
ss.str(s);
ss>>t;
while(t--){
getline(cin,s);
op(s);
//迭代器遍历map
map<int,int>::iterator it;
int mx=-1e9,mn=1e9;
for(it=mp.begin();it!=mp.end();it++){
if((*it).first>mx)mx=(*it).first;
if((*it).first<mn)mn=(*it).first;
}
// 下面的方法不可以,因为map是对key排序
// int mx=(*mp.begin()).first,mn=(*mp.end()).first;
// for(auto i:mp)cout<<i.first<<" "<<i.second<<endl;
sum+=(mx-mn);
mp[mx]--;mp[mn]--;
if(!mp[mx])mp.erase(mx);
if(!mp[mn])mp.erase(mn);
}
cout<<sum;
return 0;
}
op函数还可以这样写(但是容易写错)
void op(string s){
int a;
stringstream ss;
ss.clear();
ss.str(s);
ss>>a;//丢弃第一个数
while(!ss.fail()){//如果还有数
ss>>a;//这个a可能是假的
//注意坑点,下面一行代码必须加
if ( ss.fail() ) break;
mp[a]++;
}
}
易错原因:
因为读入最后一个数字后,ss仍处于正常状态,只有再尝试读入时才会出错,所以推荐第一种做法,不推荐第二种做法
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <sstream>
#define LL long long
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=a;i<n;++i)
#define foo(i,a,n) for(int i=a;i<=n;++i)
const int INF = 0x3f3f3f3f;
using namespace std;
template<class T>inline void read(T &x){
x=0; char c=getchar(); bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
}
const int N=1e6+5;
priority_queue<int> q1,q2;//默认大根堆
int a[N];
int main(){
int t,n;
LL res=0;
cin>>t;
while(t--){
read(n);
fo(i,0,n){
int x;read(x);
q1.push(x);
q2.push(-x);
a[x]++;
}
// 我得拿实际存在的数字
// int x=q1.top(),y=-q2.top();
// while(a[x]<=0)q1.pop();
// while(a[y]<=0)q2.pop();
// 上面这么写就炸了,因为q1.top()和q2.top()一直在变化
while(a[q1.top()]<=0)q1.pop();
while(a[-q2.top()]<=0)q2.pop();
int x=q1.top(),y=-q2.top();
res+=x-y;
q1.pop();q2.pop();
a[x]--;a[y]--;
}
printf("%lld",res);
return 0;
}
想建小根堆也行:priority_queue<int,vector<int>,greater<int> > q;
类似的一道字符串读入练习题:
ac:
#include<bits/stdc++.h>
using namespace std;
struct f{
string k;
int fl;
}s[1005];
bool cmp(f a,f b){return a.fl<b.fl;}
int main(){
string s1;
while(getline(cin,s1)){
stringstream s2;
s2.clear();
s2.str(s1);
int a,sum=0;
while(s2>>a)
s[sum++].fl=a;
string k1;
for(int i=0;i<sum;i++){
cin>>k1;
s[i].k=k1;
}
sort(s,s+sum,cmp);
for(int i=0;i<sum;i++)
cout<<s[i].k<<endl;
}
}