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 }
View Code

 

 

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 }
View Code

 

 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 }
View Code

 

 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 }
View Code

 

 

 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 }
View Code

 

 

end

posted on 2015-03-22 19:46  gaolzzxin  阅读(167)  评论(0编辑  收藏  举报