2015 Multi-University Training Contest 2

来源:互联网 发布:淘宝店铺运费模板 编辑:程序博客网 时间:2024/06/06 03:34

官方题解:2015 Multi-University Training Contest 2 solutions BY 学军中学


1002 Buildings

HDU 5301:http://acm.hdu.edu.cn/showproblem.php?pid=5301
题意:有一个n*m的大矩阵,其中有一个1*1的坏格,求用若干个小矩阵去覆盖大矩阵,坏格不能被覆盖。问小矩阵中面积最大的面积最小是多少。给出n,m以及坏格的位置x,y


如果没有坏格,那么答案应该是\(ans'=(min(m,n)+1)/2\)

有了坏格就要考虑坏格周围的4个格子是否能被覆盖到


交换\(n,m\)使\(n \leqslant m\),并把坏格装换到矩阵左上角

那么需要被覆盖的就是坏格下方的那个格子,只要它能被覆盖,那么其他4个格子也一定能被覆盖。

同时要注意ans的长度不会超过\((m+1)/2\)。那么\(ans=min((m+1)/2,max(ans’,min(n-x,y)))\)


特殊情况:当大矩阵为正方形,且坏格位于方形中心时,\(ans=ans'-1\)


#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define N 100005#define INF 1<<30int main() {    int n,m,x,y;    while(scanf("%d%d%d%d",&n,&m,&x,&y)!=EOF) {        if(n>m) {            swap(n,m);            swap(x,y);        }        int ans=(min(n,m)+1)/2;        x=min(x,n-x+1);        y=min(y,m-y+1);        if(n==m&&(n&1)&&x==y&&x==(n+1)/2)            ans--;        else {            ans=min((m+1)/2,max(ans,min(n-x,y)));        }        printf("%d\n",ans);    }    return 0;}


1004 Delicious Apples

HDU 5303:http://acm.hdu.edu.cn/showproblem.php?pid=5303

题意:在一个长为L的环形路上有n个苹果数,坐标为0的位置为起点。分别给出了苹果树距离起点的长度\(x_i\)(顺时针)和苹果数量\(a_i\),现在有一个最多能装\(k\)个苹果的篮子,从起点出发,往返摘取苹果,问最短的行走距离。

\(1\leqslant n ,k\leqslant 10^5,1\leqslant L\leqslant 10^9\)


如果将环路从\(\frac{L}{2}\)处断开,那么便可以左右分别贪心求出最小的\(ans\)

但因为是环形,就要考虑一种特殊情况,可能需要绕整个环一周。因为左右两边贪心完后可能剩下小于\(k\)个的苹果(如果剩下大于\(k\)个,那么大于那部分走半边就可以摘取),对于这种情况特殊处理,然后取最小值。

PS:注意用__int64


#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>#include<vector>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define N 100005#define INF 1<<30LL l[N],r[N];int l_cnt,r_cnt;int main() {    //freopen("C:\\Users\\F\\Desktop\\in.txt", "r", stdin);    //freopen("C:\\Users\\F\\Desktop\\out.txt", "w", stdout);    int t;    int n,k,L;    int x,a;    LL ans;    scanf("%d",&t);    while(t--) {        ans=0;        memset(l,0,sizeof(l));        memset(r,0,sizeof(r));        l_cnt=1;        r_cnt=1;        scanf("%d%d%d",&L,&n,&k);        for(int i=1; i<=n; ++i) {            scanf("%d%d",&x,&a);            while(a--) {                if(x*2<L)                    l[l_cnt++]=x;                else                    r[r_cnt++]=L-x;            }        }        l_cnt--,r_cnt--;        sort(l+1,l+l_cnt+1);        sort(r+1,r+r_cnt+1);        for(int i=1; i<=l_cnt; ++i) {            if(i>k) {                l[i]+=l[i-k];            }        }        for(int i=1; i<=r_cnt; ++i) {            if(i>k) {                r[i]+=r[i-k];            }        }        ans=(l[l_cnt]+r[r_cnt])*2;        for(int i=0; i<=k; ++i) {            ans=min(ans,L+(l[l_cnt-i]+r[max(0,r_cnt-(k-i))])*2);        }        printf("%I64d\n",ans);    }    return 0;}



1006 Friends

HDU 5305:http://acm.hdu.edu.cn/showproblem.php?pid=5305

题意:n个人m对朋友,对于每对朋友可以选择成为线上朋友或者线下朋友,但要求每人的线上朋友数等于线下朋友数,问有多少种选择方法

\(1\leqslant n \leqslant 8\)


当n=8时,\(\frac{8\times7}{2}=28\)条边,如果直接暴力枚举的话需要枚举\(2^{28}\approx10^8\)次,明显会TLE

考虑剪枝,如果枚举的时候考虑当前边的两点,不让点的某一种朋友数超过点度数的\(\frac{1}{2}\),便会节省掉很大一部分时间。


#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define N 100005#define INF 1<<30int n,m;int ans;int on[10],off[10];int vis[10];struct Edge {    int a,b;} e[110];void dfs(int k) {    if(k==m) {        for(int i=1; i<=n; ++i)            if(on[i]!=off[i])return;        ans++;        return ;    }    int a=e[k].a,b=e[k].b;    if(on[a]<vis[a]/2&&on[b]<vis[b]/2) {        on[a]++,on[b]++;        dfs(k+1);        on[a]--,on[b]--;    }    if(off[a]<vis[a]/2&&off[b]<vis[b]/2) {        off[a]++,off[b]++;        dfs(k+1);        off[a]--,off[b]--;    }}int main() {    int T;    scanf("%d",&T);    while(T--) {        scanf("%d%d",&n,&m);        ans=0;        int flag=0;        memset(vis,0,sizeof(vis));        memset(on,0,sizeof(on));        memset(off,0,sizeof(off));        for(int i=0; i<m; ++i) {            scanf("%d%d",&e[i].a,&e[i].b);            vis[e[i].a]++;            vis[e[i].b]++;        }        for(int i=1; i<=n; ++i) {            if(vis[i]&1)flag=1;        }        if(flag) {            printf("0\n");            continue;        }        dfs(0);        printf("%d\n",ans);    }    return 0;}


1007 Gorgeous Sequence

HDU 5306:http://acm.hdu.edu.cn/showproblem.php?pid=5306
题意:一个长度为n的序列a,定义三种操作:

0 x y t: 对于\(x\leqslant i \leqslant y\),令\(a_i=min(a_i,t)\)

1 x y: 输出区间\([x,y]\)内的最大值

2 x y: 输出区间\([x,y]\)内的数的和


线段树区间合并

用一个cover数组去记录lazy标记影响了多少个数


用平时的输入外挂还过不了。。贴一个标程的输入外挂

/************Read**********/char *ch, *ch1, buf[40*1024000+5], buf1[40*1024000+5];void read(int &x){    for (++ch; *ch <= 32; ++ch);    for (x = 0; '0' <= *ch; ch++)    x = x * 10 + *ch - '0';}/**************************/int main(){    ch = buf - 1;    ch1 = buf1 - 1;    fread(buf, 1, 1000 * 35 * 1024, stdin);    int x;    read(x);    return 0;}

AC代码

#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>#include<vector>#include<string>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define N 1000005#define INF 1<<30#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1/************Read**********/char *ch, *ch1, buf[40*1024000+5], buf1[40*1024000+5];void read(int &x){    for (++ch; *ch <= 32; ++ch);    for (x = 0; '0' <= *ch; ch++)    x = x * 10 + *ch - '0';}/**************************/LL sum[N<<2];int mmax[N<<2];int tag[N<<2];int cover[N<<2];void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];    mmax[rt]=max(mmax[rt<<1],mmax[rt<<1|1]);    cover[rt]=cover[rt<<1]+cover[rt<<1|1];}void mark(int t,int l,int r,int rt){    if(tag[rt]!=0&&tag[rt]<=t)return;    tag[rt]=t;    if(cover[rt]!=r-l+1){        mmax[rt]=t;        sum[rt]+=(LL)(r-l+1-cover[rt])*t;        cover[rt]=r-l+1;    }}void pushdown(int l,int r,int rt){    if(tag[rt]){        int m=(l+r)>>1;        mark(tag[rt],lson);        mark(tag[rt],rson);    }}void build(int l,int r,int rt){    tag[rt]=0;    if(l==r){        read(tag[rt]);        sum[rt]=mmax[rt]=tag[rt];        cover[rt]=1;        return;    }    int m=(l+r)>>1;    build(lson);    build(rson);    pushup(rt);}void clear(int t,int l,int r,int rt){    if(mmax[rt]<t)return;    if(tag[rt]>=t)        tag[rt]=0;    if(l==r){        sum[rt]=mmax[rt]=tag[rt];        cover[rt]=(tag[rt]!=0);        return;    }    int m=(l+r)>>1;    pushdown(l,r,rt);    clear(t,lson);    clear(t,rson);    pushup(rt);}void update(int L,int R,int t,int l,int r,int rt){    if(mmax[rt]<=t)return;    if(L<=l&&r<=R){        clear(t,l,r,rt);        if(l==r){            sum[rt]=mmax[rt]=tag[rt]=t;            cover[rt]=1;        }else{            pushup(rt);        }        mark(t,l,r,rt);        return;    }    int m=(l+r)>>1;    pushdown(l,r,rt);    if(L<=m)update(L,R,t,lson);    if(R>m)update(L,R,t,rson);    pushup(rt);}LL query(int L,int R,int op,int l,int r,int rt){    if(L<=l&&r<=R){        switch(op){            case 1:return mmax[rt];break;            case 2:return sum[rt];break;        }    }    int m=(l+r)>>1;    LL ret=0;    pushdown(l,r,rt);    if(L<=m){        switch(op){            case 1:ret=max(ret,query(L,R,op,lson));break;            case 2:ret+=query(L,R,op,lson);break;        }    }    if(R>m){         switch(op){            case 1:ret=max(ret,query(L,R,op,rson));break;            case 2:ret+=query(L,R,op,rson);break;        }    }    pushup(rt);    return ret;}void show(int l,int r,int rt){    if(l==r){        printf("%I64d",sum[rt]);        return ;    }    int m=(l+r)>>1;    pushdown(l,r,rt);    show(lson);    show(rson);    pushup(rt);}int main(){    ch = buf - 1;    ch1 = buf1 - 1;    fread(buf, 1, 1000 * 35 * 1024, stdin);    int T;    int n,m;    int op,x,y,t;    read(T);    while(T--){        read(n);        read(m);        build(1,n,1);        while(m--){            read(op);            read(x);            read(y);            if(op==0){                read(t);                update(x,y,t,1,n,1);            }else if(op==1){                printf("%d\n",query(x,y,1,1,n,1));            }else{                printf("%I64d\n",query(x,y,2,1,n,1));            }        }    }    return 0;}



1009 I Wanna Become A 24-Point Master

HDU 5308:http://acm.hdu.edu.cn/showproblem.php?pid=5308
题意:给n个整数n,用“+”,“-”,“*”,“/”,括号凑24点。

\(1\leqslant n \leqslant 10^5\)


对于\(n<15\)时可以打表:

\(n\leqslant 3,\)无解

\(n=4,4*4+4+4=24\)

\(n=5,(5-\frac{\frac{5}{5}}{5})\times 5=24\)

\(n=6,6+6+6+6=24\)

\(n=7,\frac{7\times7-\frac{7}{7}}{7+7}\times7=24\)

\(n=8,8+8+8=24\)

\(n=9,9+9+9-\frac{9}{9}-\frac{9}{9}-\frac{9}{9}=24\)

\(n=10,10+10+\frac{10+10}{10}+\frac{10+10}{10}=24\)

\(n=11,11+11+\frac{11+11}{11}=24\)

\(n=12,12+12=24\)

\(n=13,13+13-\frac{13+13}{13}=24\)

\(n=14,14+14-\frac{14+14}{14}-\frac{14+14}{14}=24\)

对于\(n\geqslant 15\):

\(\frac{n+n}{n}*\frac{n+n}{n}*\frac{n+n}{n}*\frac{n+n+n}{n}=24\)

对于多余的n可以用两个n相减得0,在把多余的n乘掉。

#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define N 100005#define INF 1<<30int main() {    //freopen("C:\\Users\\F\\Desktop\\in.txt", "r", stdin);    //freopen("C:\\Users\\F\\Desktop\\out.txt", "w", stdout);    int n;    while(scanf("%d",&n)!=EOF) {        if(n<=3)            printf("-1\n");        else {            if(n==4) {                printf("1 * 2\n");                printf("5 + 3\n");                printf("6 + 4\n");            } else if(n==5) {                printf("1 / 2\n");//6                printf("6 / 3\n");//7                printf("4 - 7\n");//8                printf("5 * 8\n");//9            } else if(n==6) {                printf("1 + 2\n");                printf("7 + 3\n");                printf("8 + 4\n");                printf("9 + 5\n");                printf("10 - 6\n");            } else if(n==7) {                printf("1 / 2\n");//8                printf("3 * 4\n");//9                printf("9 - 8\n");//10                printf("5 + 6\n");//11                printf("10 / 11\n");//12                printf("12 * 7\n");//13            } else if(n==8) {                printf("1 + 2\n");//9                printf("9 + 3\n");//10                printf("4 - 5\n");//11                printf("11 * 6\n");//12                printf("12 * 7\n");//13                printf("13 * 8\n");//14                printf("10 + 14\n");//15            } else if(n==9) {                printf("1 + 2\n");//10                printf("10 + 3\n");//11                printf("4 / 5\n");//12                printf("6 / 7\n");//13                printf("8 / 9\n");//14                printf("11 - 12\n");//15                printf("15 - 13\n");//16                printf("16 - 14\n");//17            } else if(n==10) {                printf("1 + 2\n");//11                printf("3 + 4\n");//12                printf("12 / 5\n");//13                printf("11 + 13\n");//14                printf("6 + 7\n");//15                printf("15 / 8\n");//16                printf("14 + 16\n");//17                printf("17 + 9\n");//18                printf("18 - 10\n");//19            } else if(n==11) {                printf("1 + 2\n");//12                printf("3 + 4\n");//13                printf("13 / 5\n");//14                printf("12 + 14\n");//15                printf("6 - 7\n");//16                printf("16 * 8\n");//17                printf("17 * 9\n");//18                printf("18 * 10\n");//19                printf("19 * 11\n");//20                printf("20 + 15\n");//20            } else if(n==12) {                printf("1 + 2\n");//13                printf("3 - 4\n");//14                printf("14 * 5\n");//15                printf("15 * 6\n");//16                printf("16 * 7\n");//17                printf("17 * 8\n");//18                printf("18 * 9\n");//19                printf("19 * 10\n");//20                printf("20 * 11\n");//21                printf("21 * 12\n");//22                printf("22 + 13\n");//23            } else if(n==13) {                printf("1 + 2\n");//14                printf("3 + 4\n");//15                printf("15 / 5\n");//16                printf("14 - 16\n");//17                printf("6 - 7\n");//18                printf("18 * 8\n");//19                printf("19 * 9\n");//20                printf("20 * 10\n");//21                printf("21 * 11\n");//22                printf("22 * 12\n");//23                printf("23 * 13\n");//24                printf("24 + 17\n");//25            } else if(n==14) {                printf("1 + 2\n");//15                printf("3 + 4\n");//16                printf("16 / 5\n");//17                printf("15 - 17\n");//18                printf("6 + 7\n");//19                printf("19 / 8\n");//20                printf("18 - 20\n");//21                printf("9 - 10\n");//22                printf("22 * 11\n");//23                printf("23 * 12\n");//24                printf("24 * 13\n");//25                printf("25 * 14\n");//26                printf("26 + 21\n");//27            } else {                printf("1 + 2\n");//1                printf("%d / 3\n",n+1);//2                printf("4 + 5\n");//3                printf("%d / 6\n",n+3);//4                printf("%d * %d\n",n+2,n+4);//5                printf("7 + 8\n");//6                printf("%d / 9\n",n+6);//7                printf("%d * %d\n",n+5,n+7);//8                printf("10 + 11\n");//9                printf("%d + 12\n",n+9);//10                printf("%d / 13\n",n+10);//11                printf("%d * %d\n",n+8,n+11);//12                printf("14 - 15\n");//13                int lnow=n+13;                int now=16;                while(now<=n) {                    printf("%d * %d\n",lnow++,now++);                }                printf("%d + %d\n",lnow,n+12);            }        }    }    return 0;}


(待续。。。)


0 0