官方题解: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<<30
int 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<<30
LL 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<<30
int 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<<30
int 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;
}
(待续。。。)