2015_3
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=72571#problem/A
A 取最值,h最大,h相同时面积最大,排序解决。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int M=128; 5 struct G{ 6 int h,val; 7 friend bool operator <(const G &a,const G &b){ 8 return a.h>b.h||(a.h==b.h&&a.val>b.val); 9 } 10 }g[M]; 11 int main(){ 12 int n,l,w,h; 13 while(~scanf("%d",&n),n){ 14 for(int i=0;i<n;i++){ 15 scanf("%d%d%d",&l,&w,&h); 16 g[i].h=h; 17 g[i].val=l*w*h; 18 } 19 sort(g,g+n); 20 printf("%d\n",g[0].val); 21 } 22 return 0; 23 }
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=72571#problem/D
D L*L个数字中至少取m个至多取n个的方法数。排列解决,答案为 A(l*l,i)m<=i<=n. l*l中取i个,阶乘暴力算,取m+1个可由取m个的结果再乘上一个数得到。
1 #include<cstdio> 2 typedef long long LL; 3 LL mod=1e13+7; 4 int main(){ 5 int t,l,m,n; 6 while(~scanf("%d",&t)){ 7 int cas=1; 8 while(t--){ 9 scanf("%d%d%d",&l,&m,&n); 10 LL tmp=l*l; 11 LL mul=1; 12 for(int i=0;i<m;i++){ 13 mul*=tmp; 14 mul%=mod; 15 tmp--; 16 } 17 LL ans=mul; 18 for(int i=m+1;i<=n;i++){ 19 mul*=tmp; 20 mul%=mod; 21 tmp--; 22 ans+=mul; 23 ans%=mod; 24 } 25 printf("Case %d: %lld\n",cas++,ans); 26 } 27 } 28 return 0; 29 }
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=72571#problem/F
F 构造出与已知线段垂直且不会超过正方形的一个线段。通过已知的两个坐标取最大值得到s的最小值,然后让整个正方形旋转90度,得到的新的两个坐标恰好符合题意。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int main(){ 5 int t,x1,y1,x2,y2; 6 while(~scanf("%d",&t)){ 7 int cas=1; 8 while(t--){ 9 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 10 int s=max(x1,y1); 11 s=max(s,x2); 12 s=max(s,y2); 13 printf("Case %d: %d %d %d %d\n",cas++,y1,s-x1,y2,s-x2); 14 } 15 } 16 return 0; 17 }
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=72571#problem/G
G 有n个区间m个查询,每个查询对于所有的区间,若查询值在区间外,得0分,查询值在区间内,得min(x-L,R-x)分,也就是和两端较近一端的距离,最后对于每个查询,输出所有区间得分的最高分。区间和查询都是10的5次方。
做法,查询就是数轴上的一些点,一开始得分都是0,枚举区间10的5次方,对于每一个区间,他只能影响区间内的点,这时候用线段树的区间更新将影响的点的更新降到logn。
注意几个问题,一是区间和查询的值10的9次方,需要对数值离散化。
二是根据得分的定义,区间左半边的点都只被L影响,右半边的点只被R影响,所以离散化需要多一个区间的中点,一个区间相当于两个区间
三是离散化有LRMq,q是查询,所以线段树空间要4*10的5次方
四是对于每一个x,都用线段树记录最靠左和最靠右的值,最终答案一定出自这两个之一,所以线段树要记录一个最小值一个最大值
五是最后要一次性把lazy推到底,不要边遍历q边query线段树,那样超时。。
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<map> 5 #define lrrt int L,int R,int rt 6 #define iall 1,index,1 7 #define imid int mid=(L+R)>>1 8 #define lson L,mid,rt<<1 9 #define rson mid+1,R,rt<<1|1 10 using namespace std; 11 const int inf=0x3f3f3f3f; 12 const int M=4e5+10; 13 struct QU{ 14 int L,R,M; 15 }qu[M]; 16 vector<int> lisan; 17 map<int,int> bigtosma,smatobig; 18 int q[M]; 19 struct T{ 20 int big,sma; 21 }tree[M<<2]; 22 void build(lrrt){ 23 tree[rt].big=0; 24 tree[rt].sma=inf; 25 if(L==R) return ; 26 imid; 27 build(lson); 28 build(rson); 29 } 30 void pushdown(int rt){ 31 if(tree[rt<<1].big<tree[rt].big) tree[rt<<1].big=tree[rt].big; 32 if(tree[rt<<1].sma>tree[rt].sma) tree[rt<<1].sma=tree[rt].sma; 33 if(tree[rt<<1|1].big<tree[rt].big) tree[rt<<1|1].big=tree[rt].big; 34 if(tree[rt<<1|1].sma>tree[rt].sma) tree[rt<<1|1].sma=tree[rt].sma; 35 } 36 void update(int x,int y,int z,lrrt){ 37 if(x<=L&&R<=y){ 38 if(tree[rt].big<z) tree[rt].big=z; 39 if(tree[rt].sma>z) tree[rt].sma=z; 40 return ; 41 } 42 imid; 43 pushdown(rt); 44 if(mid>=x) update(x,y,z,lson); 45 if(mid<y) update(x,y,z,rson); 46 } 47 int big[M],sma[M]; 48 void query(lrrt){ 49 if(L==R){ 50 big[L]=tree[rt].big; 51 sma[L]=tree[rt].sma; 52 return ; 53 } 54 imid; 55 pushdown(rt); 56 query(lson); 57 query(rson); 58 } 59 int main(){ 60 int t,n,m; 61 while(~scanf("%d",&t)){ 62 int cas=1; 63 while(t--){ 64 scanf("%d%d",&n,&m); 65 lisan.clear(); 66 bigtosma.clear(); 67 smatobig.clear(); 68 for(int i=0;i<n;i++){ 69 scanf("%d%d",&qu[i].L,&qu[i].R); 70 qu[i].M=(qu[i].L+qu[i].R)/2; 71 lisan.push_back(qu[i].L); 72 lisan.push_back(qu[i].R); 73 lisan.push_back(qu[i].M); 74 } 75 for(int i=0;i<m;i++){ 76 scanf("%d",&q[i]); 77 lisan.push_back(q[i]); 78 } 79 sort(lisan.begin(),lisan.end()); 80 int len=unique(lisan.begin(),lisan.end())-lisan.begin(); 81 int index=1; 82 for(int i=0;i<len;i++){ 83 bigtosma[lisan[i]]=index; 84 smatobig[index]=lisan[i]; 85 index++; 86 } 87 build(iall); 88 for(int i=0;i<n;i++){ 89 int l=bigtosma[qu[i].L]; 90 int m=bigtosma[qu[i].M]; 91 int r=bigtosma[qu[i].R]; 92 update(l,m,l,iall); 93 update(m+1,r,r,iall); 94 } 95 query(iall); 96 printf("Case %d:\n",cas++); 97 for(int i=0;i<m;i++){ 98 int id=bigtosma[q[i]]; 99 int ans=0; 100 if(big[id]!=0){ 101 ans=max(ans,smatobig[big[id]]-q[i]); 102 } 103 if(sma[id]!=inf){ 104 ans=max(ans,q[i]-smatobig[sma[id]]); 105 } 106 printf("%d\n",ans); 107 } 108 } 109 } 110 return 0; 111 }
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=72571#problem/J
J 求有多少个字串满足重排之后是回文。
比赛时用了亦或,其实直接统计就行,用两个变量记录一下奇数和偶数的字母分别有多少种,要是回文则奇数的字母只能有一种或者没有。
1 #include<cstdio> 2 #include<cstring> 3 #define mt(a,b) memset(a,b,sizeof(a)) 4 const int M=1024; 5 char a[M]; 6 int cnt[32]; 7 int main(){ 8 int t; 9 while(~scanf("%d",&t)){ 10 int cas=1; 11 while(t--){ 12 scanf("%s",a); 13 int ans=0; 14 int la=strlen(a); 15 for(int i=0;i<la;i++){ 16 int ji=0,ou=26; 17 mt(cnt,0); 18 for(int j=i;j<la;j++){ 19 int now=a[j]-'a'; 20 cnt[now]++; 21 if(cnt[now]&1){ 22 ji++; 23 ou--; 24 } 25 else{ 26 ou++; 27 ji--; 28 } 29 if(ji<2) ans++; 30 } 31 } 32 printf("Case %d: %d\n",cas++,ans); 33 } 34 } 35 return 0; 36 }
end