2015年百度之星程序设计大赛 - 初赛(1)

A.5246 超级赛亚ACMer

显然要先排序,然后每次在能达到的最大的时候打平,这样的话就可以最大程度的利用k。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define FIR first
#define SEC second
#define MP make_pair
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 100100;

LL a[maxn];
int n, m, k;

bool check()
{
    int id = upper_bound(a + 1, a + n + 1, m) - a;
    id --;
    LL tmp = a[id];
    for(int i = id + 1; i <= n; i ++)
    {
        if(tmp + k < a[i]) return false;
        while(tmp + k >= a[i + 1]) i ++;
        tmp = a[i];
        k --;
    }
    return true;
}

int main()
{
    int T, cas = 1;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= n; i ++)
        {
            scanf("%I64d", &a[i]);
        }
        sort(a + 1, a + n + 1);
        printf("Case #%d:\n", cas ++);
        if(m < a[1])
        {
            puts("madan!");
        }
        else if(a[n] <= m)
        {
            puts("why am I so diao?");
        }
        else
        {
            if(check()) puts("why am I so diao?");
            else puts("madan!");
        }
    }
    return 0;
}

B.5247 找连续数

n*m=1e7,正好可以暴力,然后对于每个询问,我们只需要看所的k段长度最大值-最小值是否=k-1而且区间里不同元素的个数就行了。最大值和最小值可以用一个单调队列。不同元素的个数可以先离散化,然后用数组统计个数就ok了

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define FIR first
#define SEC second
#define MP make_pair
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 100100;

int a[maxn], id[maxn], n, cnt[maxn];

int big[maxn], sml[maxn];

int solve(int k)
{
    int l1 = 0, sz1 = 1, l2 = 0, sz2 = 1;
    big[0] = a[1];
    sml[0] = a[1];
    int num = 1;
    for(int i = 1; i <= n; i ++) cnt[i] = 0;
    cnt[id[1]] ++;
    for(int i = 2; i <= k; i ++)
    {
        if(cnt[id[i]] == 0) num ++;
        cnt[id[i]] ++;
        while(sz1 > 0 && big[sz1 - 1] < a[i])
        {
            sz1 --;
        }
        big[sz1 ++] = a[i];
        while(sz2 > 0 && sml[sz2 - 1] > a[i])
        {
            sz2 --;
        }
        sml[sz2 ++] = a[i];
    }
    int ret = 0;
    if(num == k && big[l1] - sml[l2] == k - 1) ret ++;
    for(int i = k + 1; i <= n; i ++)
    {
        if(cnt[id[i]] == 0) num ++;
        cnt[id[i]] ++;
        if(cnt[id[i-k]] == 1) num --;
        cnt[id[i-k]] --;
        while(sz1 > l1 && big[sz1 - 1] < a[i])
        {
            sz1 --;
        }
        big[sz1 ++] = a[i];
        if(a[i-k] == big[l1]) l1 ++;
        while(sz2 > l2 && sml[sz2 - 1] > a[i])
        {
            sz2 --;
        }
        sml[sz2 ++] = a[i];
        if(a[i-k] == sml[l2]) l2 ++;
        if(num == k && big[l1] - sml[l2] == k - 1) ret ++;
    }
    return ret;
}

int main()
{
    int T, cas = 1, m;
//    scanf("%d", &T);
    while(scanf("%d%d", &n, &m) != EOF)
    {

        vector<int> vec;
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d", &a[i]);
            vec.push_back(a[i]);
        }
        sort(vec.begin(), vec.end());
        vec.erase(unique(vec.begin(), vec.end()), vec.end());
        for(int i = 1; i <= n; i ++)
        {
            id[i] = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
        }
        printf("Case #%d:\n", cas ++);
        while(m --)
        {
            int k; scanf("%d", &k);
            if(k > n) puts("0");
            else printf("%d\n", solve(k));
        }
    }
    return 0;
}
C.5248 序列变换

这种最大值最小的问题,肯定二分+check就行了。对于每个ans,都可以把数变成一个区间,现在就是要看所有的区间能不能有一条上升的折线。简单验证下就可以了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define FIR first
#define SEC second
#define MP make_pair
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 100200;

int a[maxn];

bool check(int sub, int n)
{
    int l = a[1] - sub, r = a[1] + sub;
    for(int i = 2; i <= n; i ++)
    {
        int tl = a[i] - sub, tr = a[i] + sub;
        l = max(tl, l + 1);
        r = tr;
        if(l > r) return false;
    }
    return true;
}

int main()
{
    int n, T, cas = 1;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d", &a[i]);
        }
        int l = 0, r = 10001000;
        while(l <= r)
        {
            int mid = (l + r) >> 1;
            if(check(mid, n))
                r = mid - 1;
            else l = mid + 1;
        }
        printf("Case #%d:\n%d\n", cas ++, l);
    }
    return 0;
}
D.5249 KPI
 离线做的话其实就是问的区间第k大,划分树或者主席树都可以做。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define FIR first
#define SEC second
#define MP make_pair
#define LL long long
#define ULL unsigned long long
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

#define MID ((l+r)>>1)

const int maxn = 100100;
const int INF = 0x3f3f3f3f;

int a[maxn];

struct KthNumber
{
    int s[maxn], t[20][maxn], num[20][maxn];

    void init(int n)
    {
        for(int i = 1; i <= n; i ++)
        {
            s[i] = t[0][i] = a[i];
        }
        sort(s+1, s+n+1);
    }

    void Build(int c, int l, int r)
    {
        int lm = MID-l+1, lp = l, rp = MID+1;
        for(int i = l; i <= MID; i ++)
            lm -= s[i] < s[MID];
        for(int i = l; i <= r; i ++)
        {
            if(i == l) num[c][i] = 0;
            else num[c][i] = num[c][i - 1];

            if(t[c][i] == s[MID])
            {
                if(lm)
                {
                    lm --; num[c][i] ++;
                    t[c+1][lp++] = t[c][i];
                }
                else t[c+1][rp++] = t[c][i];
            }
            else if(t[c][i] < s[MID])
            {
                num[c][i] ++;
                t[c+1][lp++] = t[c][i];
            }
            else t[c+1][rp++] = t[c][i];
        }
        if(l<r)
            Build(c+1, l, MID), Build(c+1, MID+1, r);
    }

    int Query(int c, int l, int r, int ql, int qr, int k)
    {
        if(l == r) return t[c][l];
        int s, ss;
        if(l == ql) s = 0, ss = num[c][qr];
        else s = num[c][ql-1], ss = num[c][qr]-num[c][ql-1];
        if(k <= ss) return Query(c+1, l, MID, l+s, l+s+ss-1, k);
        else return Query(c+1, MID+1, r, MID+1+ql-l-s, MID+1+qr-l-s-ss, k-ss);
    }
}sol;

struct Query
{
    char op[20];
    int x;
}q[maxn];

int main()
{
    int n, T, cas = 1;
    while(scanf("%d", &n) != EOF)
    {

        int m = 1;
        for(int i = 0; i < n; i ++)
        {
            scanf("%s", q[i].op);
            if(q[i].op[0] == 'i')
            {
                scanf("%d", &q[i].x);
                a[m ++] =  q[i].x;
            }
        }
        m --;
//        printf("%d===\n", m);
//        for(int i = 1; i <= m; i ++)
//        {
//            printf("%d ", a[i]);
//        }puts("");
        sol.init(m);
        sol.Build(0, 1, m);
        int l = 1, r = 0;
        printf("Case #%d:\n", cas ++);
        for(int i = 0; i < n; i ++)
        {
            if(q[i].op[0] == 'i')
            {
                r ++;
            }
            else if(q[i].op[0] == 'o')
            {
                l ++;
            }
            else
            {
                int k = (r - l + 1) / 2 + 1;
//                printf("%d -- %d  %d\n", l, r, k);
                printf("%d\n", sol.Query(0, 1, m, l, r, k));
            }
        }
    }
    return 0;
}
E.5250 三阶魔方

其实就是暴力找出置换,然后最大 公倍数就可以了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define FIR first
#define SEC second
#define MP make_pair
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

int id[7][4][4];
int s[70];

void init()
{
    int tot = 1;
    for(int i = 0; i < 6; i ++)
    {
        for(int j = 0; j < 3; j ++)
        {
            for(int k = 0; k < 3; k ++)
                id[i][j][k] = tot ++;
        }
    }
}

char op[222];
int tmp[7][4][4];

void Rotate(int i)
{
    for(int j = 0; j < 3; j ++)
    {
        for(int k = 0; k < 3; k ++)
        {
            tmp[i][j][k] = id[i][2 - k][j];
        }
    }
}

void idtotmp()
{
    for(int i = 0; i < 6; i ++)
    {
        for(int j = 0; j < 3; j ++)
        {
            for(int k = 0; k < 3; k ++)
                tmp[i][j][k] = id[i][j][k];
        }
    }
}

void tmptoid()
{
    for(int i = 0; i < 6; i ++)
    {
        for(int j = 0; j < 3; j ++)
        {
            for(int k = 0; k < 3; k ++)
                id[i][j][k] = tmp[i][j][k];
        }
    }
}


void gaoU(int t)
{
    while(t --)
    {
    idtotmp();
        Rotate(0);
        for(int i = 0; i < 3; i ++)
        {
            tmp[1][0][i] = id[2][0][i];
            tmp[2][0][i] = id[3][0][i];
            tmp[3][0][i] = id[4][0][i];
            tmp[4][0][i] = id[1][0][i];
        }
    tmptoid();
    }
}

void gaoR(int t)
{
//    t*=2;
    while(t --)
    {
        idtotmp();
//    printf("R %d\n", t);
        Rotate(2);
        for(int i = 0; i < 3; i ++)
        {
            tmp[0][2][i] = id[1][2 - i][2];
            tmp[1][2 - i][2] = id[5][2][i];
            tmp[5][2][i] = id[3][i][0];
            tmp[3][i][0] = id[0][2][i];
        }
        tmptoid();
    }
}

void gaoF(int t)
{
    while(t --)
    {
    idtotmp();
        Rotate(1);
        for(int i = 0; i < 3; i ++)
        {
            tmp[0][i][0] = id[4][2 - i][2];
            tmp[4][2 - i][2] = id[5][2 - i][2];
            tmp[5][2 - i][2] = id[2][i][0];
            tmp[2][i][0] = id[0][i][0];
        }
    tmptoid();
    }
}

void gaoD(int t)
{
    while(t --)
    {
    idtotmp();
        Rotate(5);
        for(int i = 0; i < 3; i ++)
        {
            tmp[2][2][i] = id[1][2][i];
            tmp[3][2][i] = id[2][2][i];
            tmp[4][2][i] = id[3][2][i];
            tmp[1][2][i] = id[4][2][i];
        }
    tmptoid();
    }
}

void gaoL(int t)
{
    while(t --)
    {
    idtotmp();
        Rotate(4);
        for(int i = 0; i < 3; i ++)
        {
            tmp[1][2 - i][0] = id[0][0][i];
            tmp[0][0][i] = id[3][i][2];
            tmp[3][i][2] = id[5][0][i];
            tmp[5][0][i] = id[1][2 - i][0];
        }
    tmptoid();
    }
}

void gaoB(int t)
{
    while(t --)
    {
    idtotmp();
        Rotate(3);
        for(int i = 0; i < 3; i ++)
        {
            tmp[0][i][2] = id[2][i][2];
            tmp[2][i][2] = id[5][2 - i][0];
            tmp[5][2 - i][0] = id[4][2 - i][0];
            tmp[4][2 - i][0] = id[0][i][2];
        }
    tmptoid();
    }
}

LL gcd(LL a, LL b)
{
    return b ? gcd(b, a % b) : a;
}

void prt()
{
    for(int i = 0; i < 6; i ++)
    {
        for(int j = 0; j < 3; j ++)
        {
            for(int k = 0; k < 3; k ++)
            {
                printf("%02d ", id[i][j][k]);
            }puts("");
        }puts("");
    }puts("----");
}
int main()
{
    int T, cas = 1;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%s", op);
        init();
        int len = strlen(op);
        for(int i = 0; i < len; i ++)
        {
            if(op[i] == 'L')
            {
                if(op[i + 1] == '\'') gaoL(3);
                else if(op[i + 1] == '2') gaoL(2);
                else gaoL(1);
            }
            else if(op[i] == 'R')
            {
                if(op[i + 1] == '\'') gaoR(3);
                else if(op[i + 1] == '2') gaoR(2);
                else gaoR(1);
            }
            else if(op[i] == 'U')
            {
                if(op[i + 1] == '\'') gaoU(3);
                else if(op[i + 1] == '2') gaoU(2);
                else gaoU(1);
            }
            else if(op[i] == 'D')
            {
                if(op[i + 1] == '\'') gaoD(3);
                else if(op[i + 1] == '2') gaoD(2);
                else gaoD(1);
            }
            else if(op[i] == 'F')
            {
                if(op[i + 1] == '\'') gaoF(3);
                else if(op[i + 1] == '2') gaoF(2);
                else gaoF(1);
            }
            else if(op[i] == 'B')
            {
                if(op[i + 1] == '\'') gaoB(3);
                else if(op[i + 1] == '2') gaoB(2);
                else gaoB(1);
            }
        }
        int tot = 1;
        for(int i = 0; i < 6; i ++)
        {
            for(int j = 0; j < 3; j ++)
            {
                for(int k = 0; k < 3; k ++)
                {
                    s[id[i][j][k]] = tot ++;
                }
            }
        }
        LL ans = 1;
        bool vis[100];
        int num = 0;
        CLR(vis, false);
        for(int i = 1; i < tot; i ++)
        {
            if(vis[i]) continue;
            int tmp = 0;
            int q = i;
            while(!vis[q])
            {
                vis[q] = true;
                tmp ++;
                q = s[q];
            }
            ans = ans / gcd(ans, tmp) * tmp;
            num ++;
        }
        printf("Case #%d:\n%I64d\n", cas ++, ans);
    }
    return 0;
}

F.5251 矩形面积

显然是凸包最小外接矩形。

#include<stdio.h>
#include<cmath>
#include<algorithm>
#define eps 1e-8
#define N 50010
using namespace std;
struct Point {
    double x,y;
    Point() {}
    Point(double x0,double y0):x(x0),y(y0) {}
};
Point p[N];
int con[N];
int cn;
int n;
double Xmult(Point o,Point a,Point b) {
    return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
}
double Dmult(Point o,Point a,Point b) {
    return (a.x-o.x)*(b.x-o.x)+(a.y-o.y)*(b.y-o.y);
}
int Sig(double a) {
    return a<-eps?-1:a>eps;
}
double Dis(Point a,Point b) {
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int cmp(Point a,Point b) {
    double d=Xmult(p[0],a,b);
    if(d>0)
        return 1;
    if(d==0 && Dis(p[0],a)<Dis(p[0],b))
        return 1;
    return 0;
}
double min(double a,double b) {
    return a<b?a:b;
}
void Graham() {
    int i,ind=0;
    for(i=1; i<n; i++)
        if(p[ind].y>p[i].y || (p[ind].y==p[i].y) && p[ind].x>p[i].x)
            ind=i;
    swap(p[ind],p[0]);
    sort(p+1,p+n,cmp);
    con[0]=0;
    con[1]=1;
    cn=1;
    for(i=2; i<n; i++) {
        while(cn>0 && Sig(Xmult(p[con[cn-1]],p[con[cn]],p[i]))<=0)
            cn--;
        con[++cn]=i;
    }
    int tmp=cn;
    for(i=n-2; i>=0; i--) {
        while(cn>tmp && Sig(Xmult(p[con[cn-1]],p[con[cn]],p[i]))<=0)
            cn--;
        con[++cn]=i;
    }
}
double Solve() {
    int t,r,l;
    double ans=999999999;
    t=r=1;
    if(cn<3)
        return 0;
    for(int i=0; i<cn; i++) {
        while(Sig( Xmult(p[con[i]],p[con[i+1]],p[con[t+1]])-
                   Xmult(p[con[i]],p[con[i+1]],p[con[t]])   )>0)
            t=(t+1)%cn;
        while(Sig( Dmult(p[con[i]],p[con[i+1]],p[con[r+1]])-
                   Dmult(p[con[i]],p[con[i+1]],p[con[r]])   )>0)
            r=(r+1)%cn;
        if(!i) l=r;
        while(Sig( Dmult(p[con[i]],p[con[i+1]],p[con[l+1]])-
                   Dmult(p[con[i]],p[con[i+1]],p[con[l]])   )<=0)
            l=(l+1)%cn;
        double d=Dis(p[con[i]],p[con[i+1]]);
        double tmp=Xmult(p[con[i]],p[con[i+1]],p[con[t]])*
                   ( Dmult(p[con[i]],p[con[i+1]],p[con[r]])-
                     Dmult(p[con[i]],p[con[i+1]],p[con[l]]) )/d/d;
        ans=min(ans,tmp);
    }
    return ans;
}
int main() {
    int i;
    int T, cas = 1;
    scanf("%d", &T);
    while(T --) {
        scanf("%d",&n);
        n *= 4;
        for(i=0; i<n; i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        Graham();
        printf("Case #%d:\n%.0f\n",cas ++, Solve());
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值