CSP集训错题集 第一周
新开这个系列,记录主播在培训过程中做不出来的一些题目。
H
这是一道比较明显关于容器的题
主播在容器这方面一直是弱项,因此刚开始做的代码是这样,用了vector里vector,喜提TLE:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
long long n,op,q,a,b;
vector<vector<int> > v(200005);
int main(){ios::sync_with_stdio(0);cin>>n;cin>>q;while(q--){cin>>op;switch(op){case 1:cin>>a>>b;v[b].push_back(a);break;case 2:cin>>a;sort(v[a].begin(),v[a].end());for(vector<int>::iterator i=v[a].begin();i<v[a].end();i++){cout<<*i<<' ';}cout<<endl;break;case 3:cin>>a;int count=0;for(int i=1;i<=n;i++){if(find(v[i].begin(),v[i].end(),a)!=v[i].end()){cout<<i<<' ';}}cout<<endl;break;}}return 0;
}
那么,做这题不TLE的方法,大概率是要学一个新的东西:
multiset容器和set容器。
可以这么理解:multiply是乘法,那么这里可能就有可以取重复的意思。对应的set就没有重复。
看其它博客说multiset里面是一个红黑树的结构,所以塞入的时候自动实现排列了。
那么回过来看这道题具体的实现:
一个盒子里面可以放重复的卡片,但是一个卡片不能说对应到某个盒子,又对应到这个盒子一次。
所以card是set,box是multiset。
对于容器,for循环内就不是普通的(i=1;i<=n;i++)
而是需要 容器名<数据类型>::iterator 打头,然后程序员习惯用it而不是i,这个it就是一个指针。
所以代码如下:
#include<iostream>
#include<set>
using namespace std;
long long n=0,q=0,op=0,x,y;
multiset<int> box[200005];
set<int> card[200005];
int main()
{cin>>n;cin>>q;while(q--){cin>>op;if(op==1){cin>>x>>y;box[y].insert(x);//盒子能放很多卡片 card[x].insert(y);//卡片对应的盒子不应重复 }else if(op==2){cin>>x;for(multiset<int>::iterator it=box[x].begin();it!=box[x].end();it++){cout<<(*it)<<' ';}cout<<endl; }else if(op==3){cin>>x;for(set<int>::iterator it=card[x].begin();it!=card[x].end();it++){cout<<(*it)<<' ';}cout<<endl;}}return 0;
}
S
思路
这题我看了下题解,发现我审错题了,重排只有一次。
说人话就是 可以拿这个方案举例
1
9 5 8
1 2 3 5 6 7 8 9 4
如果完全重排,当然是1234求和,但是这题能做到吗?显然不能,因为4在右边,123在左边。不能一次性全部翻转进区间里面,只能2选1。
翻转的对等条件是我们只能重排1 2 3 5 6 7 8 9,或者6 7 8 9 4,然后求和取min,答案为11。
#include<iostream>
#include<algorithm>
using namespace std;
long long t=0,n=0,len=0,l=0,r=0,res1=0,res2=0;
long long a[100010]={0},b[100010]={0};
int main()
{cin>>t;while(t--){cin>>n>>l>>r;len=r-l+1;res1=0;res2=0;for(int i=1;i<=n;i++){cin>>a[i];b[i]=a[i];}sort(a+1,a+1+r);for(int i=1;i<1+len;i++){//cout<<a[i]<<' ';res1+=a[i];}//cout<<res1<<endl;sort(b+l,b+1+n);for(int i=l;i<l+len;i++){//cout<<b[i]<<' ';res2+=b[i];}//cout<<res2<<endl;cout<<min(res1,res2)<<endl;}return 0;
}
喜提AC(不过比赛已经完结了)
T
思路
上面是题解,我觉得最笨的事情是我居然都没考虑到要两两一组。
后面的一些判定逻辑确实就不好想,这没办法。
这个mx的设置确实是给我干蒙了,只能说这个思维得慢慢学吧。
#include<iostream>
#include<algorithm>
using namespace std;
long long t=0,n=0;
long long a[1010]={0};
int main()
{cin>>t;while(t--){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}sort(a+1,a+1+n);long long mx=0,flag=1;for(int i=1;i<=n;i+=2){if( max(a[i], mx) != max(a[i+1], mx) ) {cout<<"No"<<endl;flag=0;break;}mx=max(mx,a[i])+1;}if(flag)cout<<"Yes"<<endl;}return 0;
}
AC了
写在最后的就是,我的代码结构还是比较垃圾,就像我们那群主说的“学习题解才是提升的唯一手段,只刷题就是浪费时间”,我下星期肯定得好好进化一下代码结构,不要再写那么多s山了。。。