2019吉首大学程序设计竞赛

B、干物妹小埋

theme:给定n栋楼的高度及到达该栋楼得到的开心值,开始可以从任一栋楼出发,下一步只会往前到>=它高度的楼,问能获得的最大开心值是多少?(0<n<=200000)

solution:就是求最长上升子序列,不过带了权,但数据范围较大,不能用常规DP,考虑用树状数组,每次就是求左边小于 该元素的以此元素结尾的子序列之和的最大值。现将楼高度从小到大排序后去重得到数组v,以排序后的数组的下标作为区间建树,则对于原数组a的每一个元素,找到>=它的第一个下标x,之后在[1,x+1]区间查询最大值,由于是按原顺序先查询后插入的,所以查询时在数组中且下标<=x的都<=a[i]

#include<bits/stdc++.h>
#define far(i,t,n) for(int i=t;i<n;++i)
#define endl "\n"
#define spa " "
#define pk(x) push_back(x)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

ll tree[200020];
int lowbit(int x)
{
    return x&(-x);
}

void update(int x,ll var)
{
    while(x<200020)
    {
        tree[x]=max(tree[x],var);
        x+=lowbit(x);
    }
}

ll query(int x)
{
    ll ans=0;
    while(x)
    {
        ans=max(ans,tree[x]);
        x-=lowbit(x);
    }
    return ans;
}

ll a[200020];
vector<ll>v;

int main()
{
    int n;
    cin>>n;
    far(i,0,n)
    {
        scanf("%lld",&a[i]);
        v.pk(a[i]);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    ll ans=0;
    far(i,0,n)
    {
        ll h;
        scanf("%lld",&h);
        int x=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;//树状数组下标从1开始
        ll tmp=query(x);
        ans=max(ans,tmp+h);
       // cout<<x<<" "<<tmp<<" "<<ans<<endl;
        update(x,tmp+h);
    }
    cout<<ans<<endl;
}

*G、说能过那是假的

theme:给定一个只由O、R、Z组成的字符串,问其中子序列ORZ个数

solution:求的子序列很短,o(n)时间即可求出。1' : 用数组r[i]记录每个i位置上为R的后续Z的个数,则从头遍历字符串,记录当前O的个数cnt,则每遇到一个R,ans+=cnt*r[i]

#include<stdio.h>
#include<string.h>
int main()
{
    char ch[100007];
    int len,ans=0;
    scanf("%s",ch);
    len=strlen(ch);
    for(int i=0;i<len;i++)
    for(int j=i+1;j<len;j++)
        for(int k=j+1;k<len;k++)
            if(ch[i]=='O'&&ch[j]=='R'&&ch[k]=='Z')
                ans++;
    printf("%d\n",ans);
}

2' : 数出所有Z的个数cntz,从头遍历一遍字符串,若为O,则cnto++,若为Z则cntz--,若为R,则ans+=cnto*cntz

#include<stdio.h>
#include<string.h>
int main()
{
    char ch[100007];
    int len;
    scanf("%s",ch);
    len=strlen(ch);
    long long cnt1,cnt2;
    cnt1=cnt2=0;
    for (int i = 0; i < len;i++){
        if(ch[i]=='Z') cnt2++;
    }
    long long ans=0;
    for (int i = 0; i < len;i++){
        if(ch[i]=='O') cnt1++;
        if(ch[i]=='Z') cnt2--;
        if(ch[i]=='R') ans+=cnt1*cnt2;
    }
    printf("%lld\n",ans);
}

hdu6536:Hello XTCPC

theme:给定一个字符串,求能形成序列xtCpc个数。1<=n<=2*10^5

solution:从前往。后记录每个相关字符已出现的个数,具体为如果所求序列中它前一个字符已出现的个数>=它才++,最后cnt[c]即为所求

#include <bits/stdc++.h>

using namespace std;
int n;
char s[200005];
int cnt[6];
int id(char x){
    if(x == 'x') return 0;
    if(x == 't') return 1;
    if(x == 'C') return 2;
    if(x == 'p') return 3;
    if(x == 'c') return 4;
    return -1;
}
int main()
{
    while(~scanf("%d",&n)){
        scanf("%s",s);
        memset(cnt,0,sizeof cnt);
        for(int i = 0;s[i];i++){
            int tt = id(s[i]);
            if(tt >= 0){
                if(tt == 0) cnt[tt]++;
                else if(cnt[tt-1] > cnt[tt]) cnt[tt]++;
            }
        }
        printf("%d\n",cnt[4]);
    }
    return 0;
}

F、天花乱坠

theme:对于一个正n边形,每次取每条边的终点连接再构造一个n边形,无穷重复下去,问所有n边形的周长之和为多少?最外边边长都为100.

 

solution: 设最外面边长为1,则下一个n边形边长为,所以其实就是以1为首项,为公比的等比数列极限求和为

#include<bits/stdc++.h>
using namespace std;
#define far(i,t,n) for(int i=t;i<n;++i)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

double pi=acos(-1);

int main()
{
    int n;
    int len=100;
    while(cin>>n)
    {
        double angle=pi/n;
        double ans=n*len;
        ans=ans/(1-cos(angle));
        printf("%.2f\n",ans);
    }
}

A、SARS病毒

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值