HPU personal training

A - Engines Atcoder 4900

题目大意:n个点,任意几个点组合后得到的点距离原点的最远距离。

题解:极角排序:https://blog.csdn.net/qq_39942341/article/details/79840394

利用极角排序,将这些点看成与原点相作用的向量,然后根据平行四边行法则,两向量之间的角度相差越小,其复合得到的向量的长度越长

#include<bits/stdc++.h>
using namespace std;
const int N=1E5+7;
struct stu{
    double a,b;
    bool friend operator <(const stu &x,const stu &y){
        return atan2(x.b,x.a)<atan2(y.b,y.a);
    }
}arr[N];
int nxt[N];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)    cin>>arr[i].a>>arr[i].b;    
    for(int i=1;i<=n;i++) nxt[i]=i+1;
    nxt[n]=1;
    sort(arr+1,arr+1+n);
    double ans=0;
    for(int i=1;i<=n;i++){//以每个点为起始点,遍历一圈后回到起始点,同时记录大小 
        double dx=arr[i].a;
        double dy=arr[i].b;
        ans=max(ans,arr[i].a*arr[i].a+arr[i].b*arr[i].b);
        
        for(int j=nxt[i];j!=i;j=nxt[j]){
            dx+=arr[j].a;
            dy+=arr[j].b;
            ans=max(ans,dx*dx+dy*dy);
        }
    }
    printf("%.15lf
",sqrt(ans));
    return 0;
}

B - Consecutive Integers

规律

#include<iostream>
using namespace std;
int main(){
    int n,k;
    cin>>n>>k;
    cout<<n-k+1<<endl;
    return 0;
}

C - ModSum

规律题。错一位取余相加

#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
    ll n;
    cin>>n;
    cout<<n*(n-1)/(ll)2<<endl;    
    return 0;
}

D - Shortest Path on a Line

 题目大意:输入一个范围。从L[i]~R[i],在这个范围内的两个数(s<t)s到t的权值为C,求点1到点N的最短距离

题解:从i到i-1建一个权值为0的反向边,这样就能使得一个范围L[i]~R[i]任意两点之间的距离为C。不足之处,仅限与求从S到T(S<T)的情况。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll INF=1E18+7;
const ll N=1E5+7;
ll n,m;
struct stu{
    ll a,b;
    bool friend operator <(const stu &x,const stu &y){
        return x.b>y.b;
    }
};
vector <stu >ve[N];
bool mark[N];
ll dp[N];
void djstrea(){
    priority_queue<stu>que;
    que.push({1,0});
    dp[1]=0;
    while(que.size()){
        stu x=que.top();
        que.pop();
        if(mark[x.a]) continue ;
        mark[x.a]=1;
        for(ll i=0;i<ve[x.a].size();i++){
            ll dx=ve[x.a][i].a;
            ll dy=ve[x.a][i].b;
            if(dp[dx]>dp[x.a]+dy){
                dp[dx]=dp[x.a]+dy;
                que.push({dx,dp[dx]});
            }
        }
    }
}
int main(){
    cin>>n>>m;
    ll x,y,z;
    for(ll i=1;i<=n;i++) {
        ve[i].push_back({i-1,0});
    }
    for(ll i=0;i<=n;i++) dp[i]=INF;
    for(ll i=1;i<=m;i++){
        cin>>x>>y>>z;
        ve[x].push_back({y,z});
    }
    djstrea();
    if(dp[n]==INF)   cout<<-1<<endl;
    else cout<<dp[n]<<endl;
    return 0;
}

E - Counting of Trees

 思维

注意1为根节点,D[i]指的是1到i的距离。所以这里0的个数必须为1,而且只能是d[1]=0,其他的地方不能出现0。然后我们在找到最大的权值,权值为i的点只能连接在权值为i-1上,因此共有arr[i-1]^arr[i]种可能;

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;

const int N=1e5+7;
const ll mod=998244353;

ll arr[N];
ll ksm(ll x,ll y){
    ll res=1;
    while(y){
        if(y&1) res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res%mod;
}

int main()
{
    ll n;
    cin>>n;
    ll x;
    ll sum=1;
    ll s=0;
    for(ll i=1;i<=n;i++){
        cin>>x;
        if(i==1&&x!=0) sum=0;
        arr[x]++;
        s=max(x,s);
    }
    for(ll i=s;i>=0;i--){
        if(arr[i]==0) sum=0;
        if(i>1){
            sum=sum*ksm(arr[i-1],arr[i])%mod;
        }
    }
    if(arr[0]>1) sum=0;
    cout<<sum%mod<<endl;
    return 0;
 } 

F - Monsters Battle Royale

模拟一下过程,始终的大的减去小的。所以答案应该为这些数的__gcd

#include<bits/stdc++.h>
using namespace std;


int main()
{
    int n;
    cin>>n;
    int g;
    for(int i=1;i<=n;i++) {
        int x;
        cin>>x;
        if(i==1){
            g=x;
        }
        else {
            g=__gcd(g,x);
        }
    }
    cout<<g<<endl;
    return 0;
}

G - Powerful Discount Tickets

 把所有的票都用完,并且每次都要给最贵的用,所有用优先队列

#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
typedef long long ll;
priority_queue<ll >que;
int main()
{
    ll n,m;
    cin>>n>>m;
    ll x;
    for(ll i=1;i<=n;i++){
        cin>>x;
        que.push(x);
    }
    ll ans=0;
    while(m--){
        ll x=que.top();
        que.pop();
        x=x/2;
        que.push(x);
    }
    while(que.size()){
        ans+=que.top();
        que.pop();
    }
    cout<<ans<<endl;
    return 0;
}

H - Attack Survival

 模拟一下就好了

#include<bits/stdc++.h>
using namespace std;
const int N=1E5+7;
int arr[N];
int main(){
    int n,k,q;
    cin>>n>>k>>q;
    for(int i=1;i<=q;i++){
        int x;    
        cin>>x;
        arr[x]++;
    }
    for(int i=1;i<=n;i++){
        int a=k-(q-arr[i]);
        if(a<=0) cout<<"No"<<endl;
        else cout<<"Yes"<<endl;
    }
    return 0;
}

I - Lower

 模拟

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1E5+7;
int arr[N];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)    cin>>arr[i];
    int ans=0;
    int sum=0;
    for(int i=n-1;i>=1;i--){
        if(arr[i]>=arr[i+1]) ans++;
        else ans=0;
        sum=max(ans,sum);
    }
    cout<<sum<<endl;
    return 0;
}

J - Kleene Inversion

 求一下单个区间内的逆序对的个数x,在求两个复合区间的逆序对的个数y,然后x*k+y*(k-1)*k/2,,取余的时候要注意,会爆longlong。

求逆序对用到了归并排序

#include<bits/stdc++.h> 
using namespace std;
const int N=5e5+7;
typedef long long ll;
const ll mod=1e9+7;
ll arr[N];
ll mark[N];
ll right_[N];
ll ans=0;
void merage_sort(ll l,ll r){
    if(l>=r) return ;
    ll mid=(l+r)/2;
    merage_sort(l,mid);
    merage_sort(mid+1,r);
    ll i=l,j=mid+1,k=l;
    while(i<=mid&&j<=r){
        if(arr[i]<=arr[j]){
            right_[k++]=arr[i++];
        }
        else {
            right_[k++]=arr[j++];
            ans+=1ll*mid-i+1;
        }
    }
    while(i<=mid)    right_[k++]=arr[i++];
    while(j<=r)   right_[k++]=arr[j++];    
    for(ll i=l;i<=r;i++)    arr[i]=right_[i];
}
int main(){
    ll n,k;
    cin>>n>>k;
    for(ll i=1;i<=n;i++){
        cin>>arr[i];
        mark[i]=arr[i];
    }
    ll ans1;
    merage_sort(1,n);
    ans1=ans;
    ll ans2=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(arr[i]>arr[j]) ans2++;
        }
    }
    cout<<(k%mod*ans1%mod+k%mod*(k-1)/2%mod*ans2%mod)%mod<<endl;
    return 0;
}

K - Two Contests

 

题目连接:https://atcoder.jp/contests/agc040/tasks/agc040_b

大佬题解:https://blog.csdn.net/duanghaha/article/details/102892233 

题意:有N个问题,每个问题可以由编号L~R之间的人完成,有两个集合S和T,将N个问题放入两个集合中,使得交集和最大

题解与证明

首先找到lmost,与rmin,当区间rmin与lmost在同一个集合中,此时答案为rmin-lmost+1+most_width(最大宽度)

当二者不再同一个集合中时,那么答案为  max((rmin-x+1)+(y-lmost+1))其中x为l[i],y为r[j]注意x与y不可以是同一个区间的左右边界。

现在已经确定了集合S中有lmost,所以,T中一定有rmin。。问题转换为一个数组,,两个参数,将这个数组划分为来年部分。使得两部分的和最大

#include<bits/stdc++.h>
using namespace std;
const int INF=1e9+7;
const int N=1E5+7;
int l[N],r[N];
int arr[N];
struct stu{
    int a,b;
    bool friend operator <(const stu &x,const stu &y){
        return x.a>y.a;
    }
}s[N];
int main()
{
    int n;
    cin>>n;
    int lmax=0,rmin=INF,width=0;
    for(int i=1;i<=n;i++){
        cin>>l[i]>>r[i];
        if(l[i]>=lmax)    lmax=l[i];
        if(r[i]<=rmin)    rmin=r[i];
        width=max(width,r[i]-l[i]+1);
    }
    int sum=max(rmin-lmax+1,0)+width;
    for(int i=1;i<=n;i++){
        s[i].a=max(0,rmin-l[i]+1);
        s[i].b=max(0,r[i]-lmax+1);
    }
    sort(s+1,s+1+n); 
    arr[n]=s[n].b;
    for(int i=n-1;i>=1;i--)    arr[i]=min(arr[i+1],s[i].b);
    int ans=0;
    for(int i=1;i<=n-1;i++)    ans=max(ans,s[i].a+arr[i+1]);
    cout<<max(ans,sum)<<endl;
    return 0;
 }

M - AB Substrings

 记录一下以b开头的字符串的数目,记录一下以a结尾的字符串的数目,在记录以b开头a结尾的字符串的数目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll aend=0,bhead=0,ab=0;
int main()
{
    int n;
    cin>>n;
    string s;
    ll ans=0;
    for(int i=1;i<=n;i++){
        cin>>s;
        int x=s.size();
        for(int j=0;j<x-1;j++){
            if(s[j]=='A'&&s[j+1]=='B')    ans++;
        }
        if(s[0]=='B'&&s[x-1]=='A') ab++;    
        if(s[0]=='B') bhead++;
        if(s[x-1]=='A') aend++;
    }
    aend-=ab;
    bhead-=ab;
    if(aend==0&&bhead==0){
        if(ab==0||ab==1) cout<<ans<<endl;
        else cout<<ans+ab-1<<endl;
    }
    else if(aend==0||bhead==0){
        cout<<ans+ab<<endl;
    }
    else if(aend!=0&&bhead!=0){
        cout<<ans+min(aend,bhead)+ab<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Accepting/p/11913932.html