vp+补题
A.(结论)
显然,把所有最大的放在一个数组里,其他放在另一个数组里就行了,注意输出格式。
#include<iostream>
#include<set>
#include<map>
using namespace std;
const int N=2e5+10;
int T,n,a[N];
void solve(){
cin>>n;
int ma=-1e9;
set<int>s;
map<int,int>mp;
for(int i=1;i<=n;i++){
cin>>a[i];
ma=max(a[i],ma);
mp[a[i]]++;
s.insert(a[i]);
}
if(s.size()==1){
cout<<-1<<endl;
return;
}
else{
int k=mp[ma];
cout<<n-k<<' '<<k<<endl;
for(int i=1;i<=n;i++)if(a[i]!=ma)cout<<a[i]<<' ';
cout<<endl;
while(k--)cout<<ma<<' ';
cout<<endl;
}
}
int main(){
cin>>T;
while(T--){
solve();
}
}
B(思维+数学)
题意,你可以任意移动数组中的元素到另外一个数组中, 经过若干次操作后。定义成本就是每个数组的最小值,然后加起来,最大化成本。我们的操作是把每行的最小值都塞到一个数组中。这样的话,成本就是所有行当前的最小值(原来的次小值)。若m是所有数的最小值,m3是所有次小值的最小值,m2为次小值,很显然 好像有点抽象哈(
#include<iostream>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
const int N=2e5+10;
int T,n;
void solve(){
vector<int>a;
cin>>n;
int m3=1e9,m=1e9;
int ans=0;
for(int i=1;i<=n;i++){
int r;
cin>>r;
int m1=1e9,m2=1e9;
for(int i=1;i<=r;i++){
int x;
cin>>x;
m=min(x,m);
if(x<m1){
m2=m1;
m1=x;
}
else if(x<m2)m2=x;
}
m3=min(m3,m2);
ans+=m2;
}
ans+=m;
ans-=m3;
cout<<ans<<endl;
}
signed main(){
cin>>T;
while(T--){
solve();
}
}
C(数学,构造)
打表发现,当取得最大值的时候,一定满足如下形式:1 2 3 …… x n n-1 …… x+1 即前面一段是正序,后面一段是逆序,枚举从哪里开始是逆序即可,复杂度O(),绰绰有余了。
#include<iostream>
using namespace std;
const int N=255;
int T,n,a[N],b[N];
void solve(){
cin>>n;
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=n;i++)b[i]=n-i+1;
///for(int i=1;i<=n;i++)cout<<b[i]<<' ';
//cout<<endl;
//枚举从哪里开始替换成n
int ans=0;
for(int now=n;now>=1;now--){
int cnt=0;
//cout<<now<<' ';
for(int i=now;i<=n;i++){
//cout<<1;
//a[now]=b[++cnt];死因
a[i]=b[++cnt];
}
//for(int i=1;i<=n;i++)cout<<a[i]<<' ';
//cout<<endl;
//计算当前的价值
int ma=0,res=0;
for(int i=1;i<=n;i++){
res+=i*a[i];
ma=max(ma,i*a[i]);
}
res-=ma;
ans=max(ans,res);
}
cout<<ans<<endl;
}
int main(){
cin>>T;
while(T--){
solve();
}
}
D(区间合并+离线操作)
对于(l,r,a,b)满足l<=a<=b<=r,我们发现,若在b<x<r的区间内,我们使用传送,一定是不优的,而我们在[l,b],我们都可以直接到b,考虑区间合并,这样就把区间划分成了若干了不相交的区间。如果直接暴力询问,复杂度是O(nq)。我们发现,对于点x越大,我们最终能到的点也越大,离线即可。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N=2e5+10;
int T,n,q;
struct node{
int x,id;
}b[N];
typedef pair<int,int>pii;
bool cmp(node a,node b){
return a.x<b.x;
}
void solve(){
cin>>n;
vector<pii>arr;
vector<pii>ve;
for(int i=1;i<=n;i++){
int l,r,a,b;
cin>>l>>r>>a>>b;
arr.push_back(make_pair(l,b));
}
cin>>q;vector<int>ans(q+1);
for(int i=1;i<=q;i++){
cin>>b[i].x;
b[i].id=i;
}
sort(b+1,b+q+1,cmp);
sort(arr.begin(),arr.end());//从小到大排序
for(int i=0;i<n;){
int x=arr[i].first;
int y=arr[i].second;
while(i<n&&arr[i].first<=y){
y=max(y,arr[i].second);
i++;
}
ve.push_back(make_pair(x,y));//这样 区间就是相互独立的
}
int now=0;int sz=ve.size();
//cout<<"check:"<<ve[sz-1].second<<endl;
for(int i=1;i<=q;i++){
int pos=b[i].x;
while(now<sz-1&&(pos>ve[now].second))now++;
//now=sz-1;
if(pos>=ve[now].first)pos=max(pos,ve[now].second);
ans[b[i].id]=pos;
}
for(int i=1;i<=q;i++)cout<<ans[i]<<' ';
cout<<endl;
}
signed main(){
cin>>T;
while(T--)solve();
return 0;
}
————————————————The END——————————————————————