ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛

来源:互联网 发布:发票数据管理软件 编辑:程序博客网 时间:2024/06/06 02:51

题目链接


01:http://hihocoder.com/problemset/problem/1578
02:http://hihocoder.com/problemset/problem/1579
03:http://hihocoder.com/problemset/problem/1580
04:http://hihocoder.com/problemset/problem/1581
05:http://hihocoder.com/problemset/problem/1582
06:http://hihocoder.com/problemset/problem/1583
07:http://hihocoder.com/problemset/problem/1584
08:http://hihocoder.com/problemset/problem/1585
09:http://hihocoder.com/problemset/problem/1586
10:http://hihocoder.com/problemset/problem/1587
这场比赛感觉自己一直在躺,划水,队友干出三道题唉。。

一些题解


01 Visiting Peking University

 题意是说给定你一串数字,再给定你每个数字能否访问的状态,那么需要在这串数字里选定k个数而这k个数里正好需要有m个是可以访问的,而剩下的是不能访问的。然后在从你选定的这m个里面选择除了第一个的一个位置使第一个位置所代表的数和你选择的位置所代表的数的和最大。
 队友直接暴力,枚举头部然后向后扩展m个可获得的值,取最大即可。

#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn=1e7+10;const int INF=0x3f3f3f3f;int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        int x[210];        bool flag[210];        memset(flag,0,sizeof(flag));        for(int i=1;i<=n;i++)            scanf("%d",&x[i-1]);        int q,p;        scanf("%d",&q);        for(int i=1;i<=q;i++)        {            scanf("%d",&p);            flag[p]=1;        }        int ans=INF;        int now=0;        int mi=INF;        int s,e;        int anss,anse,ansee;        for(int i=0;i<n;i++)        {            if(flag[i]==0)            {                 s=i,e=i,mi=INF;                int cnt=1;                while(cnt<m)                {                    e++;                    if(e>=n) break;                    if(flag[e]==0)                    {                        cnt++;                        if(x[e]<mi)                        {                            mi=x[e],anse=e;                        }                    }                }                if(e>=n) break;                now=mi+x[s];                //cout<<s<<" "<<anse<<" "<<now<<endl;                if(now<ans)                {                    ans=now;                    anss=s;                    ansee=anse;                }            }        }        printf("%d %d\n",anss,ansee);    }    return 0;}

07 Bounce

 题意是说给定一个n*m的区域,有一个小球从左上出发方向是正斜向右下,如果进入四个角则停止,如果遇到边就按反射角反弹。问你有几个格子经过且经过一次。
 队友推的公式orz, a + b - a * b - gcd(m, n)。其中a是n / gcd(n, m),b是m / gcd(n, m)。

#include <bits/stdc++.h>using namespace std;typedef long long ll;inline ll lcm(ll a,ll b){return a/__gcd(a,b)*b;}ll solve(ll a,ll b) {return a+b-a*b;}int main(){    ll n,m;    while(scanf("%lld%lld",&n,&m) != EOF)    {        if(2*n-1==m)        {            printf("%lld\n",m);            continue;        }        if(n==m)        {            printf("%lld\n",n);            continue;        }        ll gcd = __gcd(--n,--m);        ll ans = lcm(n,m)+solve(n/gcd,m/gcd);        printf("%lld\n",ans);    }    return 0;}

09 Minimum

 简单的线段树单点更新。

//线段树单点更新+RMQ#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll maxn=200005;const ll inf = 0x3f3f3f3f;#define lson (i<<1)#define rson (i<<1|1)struct {    ll l,r,MAX,MIN;}tree[4*maxn];void maintain(ll i){    tree[i].MAX=max(tree[lson].MAX,tree[rson].MAX);    tree[i].MIN=min(tree[lson].MIN,tree[rson].MIN);}void build(ll i,ll L,ll R){    tree[i].l=L,tree[i].r=R;    tree[i].MAX=tree[i].MIN=0;    if(L==R)    {        ll tmp;scanf("%lld",&tmp);        tree[i].MAX=tree[i].MIN=tmp;        return;    }    ll M=(L+R)>>1;    build(lson,L,M);    build(rson,M+1,R);    maintain(i);}void update(ll i,ll p,ll v){    ll L=tree[i].l,R=tree[i].r;    ll M=(L+R)>>1;    if(L==R && L==p)    {        tree[i].MAX=tree[i].MIN=v;        return;    }    if(M>=p)update(lson,p,v);    else update(rson,p,v);    maintain(i);}ll queryMIN(ll i,ll l,ll r){    ll L=tree[i].l,R=tree[i].r;    if(l<=L && R<=r)        return tree[i].MIN;    ll M=(L+R)>>1,_min=inf;    if(M<r) _min=queryMIN(rson,l,r);    if(M>=l) _min=min(_min,queryMIN(lson,l,r));    return _min;}ll queryMAX(ll i,ll l,ll r){    ll L=tree[i].l,R=tree[i].r;    if(l<=L && R<=r) return tree[i].MAX;    ll M=(L+R)>>1,_max=-inf;    if(M<r) _max=queryMAX(rson,l,r);    if(M>=l) _max=max(_max,queryMAX(lson,l,r));    return _max;}int main(){    ll m,t;    scanf("%lld",&t);    while(t--)    {        scanf("%lld",&m);m=(1<<m);        build(1,1,m);        ll q;scanf("%lld",&q);        while(q--)        {            ll op;scanf("%lld",&op);            ll x,y;scanf("%lld%lld",&x,&y);            if(op==2)                update(1,++x,y);            if(op==1)            {                x++;y++;                ll aa = queryMAX(1,x,y);                ll bb = queryMIN(1,x,y);                printf("%lld\n",min(min(aa*bb,aa*aa),bb*bb));            }        }    }    return 0;}
阅读全文
0 0