Codeforces Round #642 (Div. 3) A->D(D为自定义单调队列)

A: http://codeforces.com/contest/1353/problem/A

题意:构造出一个长度为n的序列,sum=m。求出最大的相邻差值的绝对值之和。a[]>=0。

解析:由于最小为0,所以可以这么构造:0,x,0,x,0,x......x为sum的平均值。那么结果总的就是2*m了。特判一下n=1和n=2

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
#define ll long long
const int maxn=40;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n,m;
        cin>>n>>m;
        if(n==1)
            cout<<'0'<<endl;
        else if(n==2)
            cout<<m<<endl;
        else
            cout<<m*2<<endl;
    }
}

 

B:http://codeforces.com/contest/1353/problem/B

题意:长度为n的两个序列a[]和b[],a[]的元素可以和b[]交换k次,求a[]的最大和。

解析:后台样例应该有点问题,我交了一发错的代码,但是过了。。。下面是思路正确的代码,模拟一下即可:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
#define ll long long
const int maxn=40;
int a[maxn],b[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,k;
        cin>>n>>k;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        for(int i=1;i<=n;i++)
            cin>>b[i];
        sort(a+1,a+1+n);
        sort(b+1,b+1+n);
        int ans=0;
        int j=n;
        for(int i=1;i<=n;i++)
        {
            if(ans==k)
                break;
            if(a[i]<b[j])
            {                
                a[i]=b[j];
                j--;
                ans++;
            }
        }
        int sum=0;
        for(int i=1;i<=n;i++)
            {
                sum+=a[i];
            //    cout<<a[i]<<"  ";
            }
        cout<<sum<<endl;
    }
}

 

C:http://codeforces.com/contest/1353/problem/C

题意:n*n的格子,每个格子各一个棋子。把所有棋子放在同一个位置所需要的最少操作数。可以朝8个方向移动。

解析:一圈一圈加就可以。可以推出公式来:sum=sum+(2*i+(i-2)*2)*ans;

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
#define ll long long
const int maxn=40;
int a[maxn],b[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n;
        cin>>n;
        ll sum=0;
        if(n==1)
        {
            cout<<"0"<<endl;continue;
        }
        if(n==3)
        {
            cout<<"8"<<endl;continue;
        }
        sum=8;
        ll ans=2;
        for(int i=5;i<=n;i+=2)
        {
            sum=sum+(2*i+(i-2)*2)*ans;
            ans++;
        }
        cout<<sum<<endl;
    }
}

D:http://codeforces.com/contest/1353/problem/D

解析:单调队列模拟。主要是排序方法注意一下,同长度L小的在前。否则长度长的在前。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
#define ll long long
const int maxn=2e5+10;
int num[maxn];
struct node
{
    int l,r;
    bool operator <(const node& a) const{
        if(a.r-a.l==r-l)
            return a.l<l;
            return a.r-a.l>r-l;
    }
}st;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        memset(num,0,sizeof(num));
        priority_queue<node>q;
        q.push(node{1,n});
        for(int i=1;i<=n;i++)
        {
            st=q.top();
            q.pop();
            int md=(st.r+st.l)/2;
            num[md]=i;
            if(md>st.l)
                q.push(node{st.l,md-1});
            if(md<st.r)
                q.push(node{md+1,st.r});
            
        }
        for(int i=1;i<=n;i++)
            cout<<num[i]<<" ";
            cout<<endl;
    }
}

 

posted @ 2020-05-15 17:04  liyexin  阅读(216)  评论(0编辑  收藏  举报