nenu contest2

 http://vjudge.net/vjudge/contest/view.action?cid=54562#overview

H  B. Polygons http://codeforces.com/problemset/problem/166/B

 目前已知两种解法,先贴一个凸包的。算法是把两个多边形的点一起做一个凸包,看这个凸包是否包含b的点,包含说明b不是严格在a内,凸包要包括边上的点。复杂度nlogn,n为两个凸包点的和n=m+n=120000。nlogn=2024720。

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 using namespace std;
 5 const double eps=1e-8;
 6 const int M=200010;
 7 struct point{
 8     double x,y;
 9     bool type;
10 }a[M],b[M];
11 bool operator < (const point &l, const point &r) {
12     return l.y < r.y || (fabs(l.y- r.y)<eps && l.x < r.x);
13 }
14 class ConvexHull { //凸包
15     bool mult(point sp, point ep, point op) {//>包括凸包边上的点,>=不包括
16         return (sp.x - op.x) * (ep.y - op.y)> (ep.x - op.x) * (sp.y - op.y);
17     }
18 public:
19     int graham(int n,point p[],point res[]) {//多边形点个数和点数组,凸包存res
20         sort(p, p + n);
21         if (n == 0) return 0;
22         res[0] = p[0];
23         if (n == 1) return 1;
24         res[1] = p[1];
25         if (n == 2) return 2;
26         res[2] = p[2];
27         int top=1;
28         for (int i = 2; i < n; i++) {
29             while (top && mult(p[i], res[top], res[top-1])) top--;
30             res[++top] = p[i];
31         }
32         int len = top;
33         res[++top] = p[n - 2];
34         for (int i = n - 3; i >= 0; i--) {
35             while (top!=len && mult(p[i], res[top],res[top-1])) top--;
36             res[++top] = p[i];
37         }
38         return top; // 返回凸包中点的个数
39     }
40 } gx;
41 int main(){
42     int n,m;
43     while(~scanf("%d",&n)){
44         for(int i=0;i<n;i++){
45             scanf("%lf%lf",&a[i].x,&a[i].y);
46             a[i].type=true;
47         }
48         scanf("%d",&m);
49         for(int i=0;i<m;i++){
50             scanf("%lf%lf",&a[i+n].x,&a[i+n].y);
51             a[i+n].type=false;
52         }
53         int lb=gx.graham(n+m,a,b);
54         bool flag=true;
55         for(int i=0;i<lb;i++){
56             if(!b[i].type){
57                 flag=false;
58                 break;
59             }
60         }
61         if(flag) puts("YES");
62         else puts("NO");
63     }
64     return 0;
65 }
View Code

 还有就是直接on判断b的点是否在a内。复杂度mlogn,m是b的点,n是a的点。mlogn=332192.

 

 1 #include<cstdio>
 2 const int M=100010;
 3 struct point{
 4     double x,y;
 5 }a[M],p;
 6 class PinConvexHull{//判断点严格在凸包内(logn)
 7     double mult(point sp,point ep,point op){
 8         return (sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y);
 9     }
10 public:
11     bool solve(point p,point a[],int n){//传入待判断点,凸包点数组,凸包点个数
12         int L=1,R=n-1;
13         while(L<=R){
14             int mid=(L+R)>>1;
15             if(mult(a[mid],p,a[0])>=0){
16                 R=mid-1;
17             }
18             else{
19                 L=mid+1;
20             }
21         }
22         if(L<2||mult(a[n-1],p,a[0])<=0||mult(a[L-1],p,a[L])<=0) {
23             return false;
24         }
25         return true;
26     }
27 }gx;
28 int main(){
29     int n,m;
30     while(~scanf("%d",&n)){
31         for(int i=0;i<n;i++){
32             scanf("%lf%lf",&a[i].x,&a[i].y);
33         }
34         scanf("%d",&m);
35         bool flag=true;
36         while(m--){
37             scanf("%lf%lf",&p.x,&p.y);
38             if(!gx.solve(p,a,n)) flag=false;
39         }
40         if(flag) puts("YES");
41         else puts("NO");
42     }
43     return 0;
44 }
View Code

 

F  Minimal Ratio Tree http://acm.hdu.edu.cn/showproblem.php?pid=2489

最小生成树克鲁斯卡尔,二进制枚举,浮点数比较加eps,输出格式不要多余空格,边的数组大小要注意,最大能n^2

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<algorithm>
  5 #define mt(a,b) memset(a,b,sizeof(a))
  6 using namespace std;
  7 const double eps=1e-8;
  8 const int inf=0x7fffffff;
  9 const int M=512;
 10 class Kruskal {  //最小生成树 kruskal 算法
 11     class UnionFindSet {//并查集
 12         int par[M];
 13     public:
 14         void init() {
 15             mt(par,-1);
 16         }
 17         int getroot(int x) {
 18             int i=x,j=x,temp;
 19             while(par[i]>=0) i=par[i];
 20             while(j!=i) {
 21                 temp=par[j];
 22                 par[j]=i;
 23                 j=temp;
 24             }
 25             return i;
 26         }
 27         bool unite(int x,int y) {
 28             int p=getroot(x);
 29             int q=getroot(y);
 30             if(p==q)return false;
 31             if(par[p]>par[q]) {
 32                 par[q]+=par[p];
 33                 par[p]=q;
 34             } else {
 35                 par[p]+=par[q];
 36                 par[q]=p;
 37             }
 38             return true;
 39         }
 40     } f;
 41     struct E {
 42         int u,v,w;
 43         friend bool operator < (E a,E b) {
 44             return a.w<b.w;
 45         }
 46     } e[M];
 47     int le,res,num,n;
 48 public:
 49     void init(int x) {
 50         n=x;
 51         le=res=0;
 52         f.init();
 53         num=1;
 54     }
 55     void add(int u,int v,int w) {
 56         e[le].u=u;
 57         e[le].v=v;
 58         e[le].w=w;
 59         le++;
 60     }
 61     void solve() {
 62         sort(e,e+le);
 63         for(int i=0; i<le&&num<n; i++) {
 64             if(f.unite(e[i].u,e[i].v)) {
 65                 num++;
 66                 res+=e[i].w;
 67             }
 68         }
 69         if(num<n) res=inf;
 70     }
 71     int getvalue() {
 72         return res;
 73     }
 74 }gx;
 75 int one(int x){
 76     int res=0;
 77     while(x){
 78         if(x&1){
 79             res++;
 80         }
 81         x>>=1;
 82     }
 83     return res;
 84 }
 85 int val[M],tmp[M],ans[M],dist[M][M];
 86 int main(){
 87     int n,m;
 88     while(~scanf("%d%d",&n,&m),n|m){
 89         for(int i=0;i<n;i++){
 90             scanf("%d",&val[i]);
 91         }
 92         for(int i=0;i<n;i++){
 93             for(int j=0;j<n;j++){
 94                 scanf("%d",&dist[i][j]);
 95             }
 96         }
 97         int big=1<<n;
 98         double sma=inf;
 99         for(int i=0;i<big;i++){
100             if(one(i)==m){
101                 int lt=0;
102                 int sumnode=0;
103                 for(int j=0;j<n;j++){
104                     if((i>>j)&1){
105                         tmp[lt++]=j;
106                         sumnode+=val[j];
107                     }
108                 }
109                 gx.init(m);
110                 for(int j=0;j<m;j++){
111                     for(int k=j+1;k<m;k++){
112                         gx.add(j,k,dist[tmp[j]][tmp[k]]);
113                     }
114                 }
115                 gx.solve();
116                 int sumedge=gx.getvalue();
117                 double now=sumedge*1.0/sumnode;
118                 if(sma>now+eps){
119                     sma=now;
120                     for(int j=0;j<m;j++){
121                         ans[j]=tmp[j];
122                     }
123                     continue;
124                 }
125                 if(fabs(sma-now)<eps){
126                     bool flag=false;
127                     for(int j=0;j<m;j++){
128                         if(tmp[j]>ans[j]) break;
129                         if(tmp[j]<ans[j]){
130                             flag=true;
131                             break;
132                         }
133                     }
134                     if(flag){
135                         for(int j=0;j<m;j++){
136                             ans[j]=tmp[j];
137                         }
138                     }
139                 }
140             }
141         }
142         for(int i=0;i<m;i++){
143             if(i) printf(" ");
144             printf("%d",ans[i]+1);
145         }
146         puts("");
147     }
148     return 0;
149 }
View Code

 最小生成树prim,一样一样的。

  1 #include<cstdio>
  2 #include<cmath>
  3 const double eps=1e-8;
  4 const int inf=0x7fffffff;
  5 const int M=32;
  6 class Prim {   //无向图最小生成树 prim,邻接阵O(n^2)必须保证图的连通的!
  7     int n,mat[M][M],dis[M],pre[M],v[M],ret,i,j,k;
  8 public:        // pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1
  9     void init(int x) {
 10         n=x;
 11         for(i=0; i<n; i++)
 12             for(j=0; j<n; j++)
 13                 mat[i][j]=i==j?0:inf;//不相邻点边权inf
 14     }
 15     void add(int u,int v,int w) {
 16         mat[u][v]=w;
 17         mat[v][u]=w;
 18     }
 19     int solve() {
 20         ret=0;
 21         for (i=0; i<n; i++) dis[i]=inf,v[i]=0,pre[i]=-1;
 22         for (dis[j=0]=0; j<n; j++) {
 23             for (k=-1,i=0; i<n; i++) if (!v[i]&&(k==-1||dis[i]<dis[k])) k=i;
 24             for (v[k]=1,ret+=dis[k],i=0; i<n; i++) if (!v[i]&&mat[k][i]<dis[i]) dis[i]=mat[pre[i]=k][i];
 25         }
 26         return ret;//返回最小生成树的长度
 27     }
 28 }gx;
 29 int val[M],tmp[M],ans[M],dist[M][M];
 30 int one(int x){
 31     int res=0;
 32     while(x){
 33         if(x&1){
 34             res++;
 35         }
 36         x>>=1;
 37     }
 38     return res;
 39 }
 40 int main(){
 41     int n,m;
 42     while(~scanf("%d%d",&n,&m),n|m){
 43         for(int i=0;i<n;i++){
 44             scanf("%d",&val[i]);
 45         }
 46         for(int i=0;i<n;i++){
 47             for(int j=0;j<n;j++){
 48                 scanf("%d",&dist[i][j]);
 49             }
 50         }
 51         int big=1<<n;
 52         double sma=inf;
 53         for(int i=0;i<big;i++){
 54             if(one(i)==m){
 55                 int lt=0,sumnode=0;
 56                 for(int j=0;j<n;j++){
 57                     if((i>>j)&1){
 58                         tmp[lt++]=j;
 59                         sumnode+=val[j];
 60                     }
 61                 }
 62                 gx.init(m);
 63                 for(int j=0;j<m;j++){
 64                     for(int k=j+1;k<m;k++){
 65                         gx.add(j,k,dist[tmp[j]][tmp[k]]);
 66                     }
 67                 }
 68                 int sumedge=gx.solve();
 69                 double now=sumedge*1.0/sumnode;
 70                 if(sma>now+eps){
 71                     sma=now;
 72                     for(int j=0;j<m;j++){
 73                         ans[j]=tmp[j];
 74                     }
 75                     continue;
 76                 }
 77                 if(fabs(sma-now)<eps){
 78                     bool flag=false;
 79                     for(int j=0;j<m;j++){
 80                         if(tmp[j]>ans[j]) break;
 81                         if(tmp[j]<ans[j]){
 82                             flag=true;
 83                             break;
 84                         }
 85                     }
 86                     if(flag){
 87                         for(int j=0;j<m;j++){
 88                             ans[j]=tmp[j];
 89                         }
 90                     }
 91                 }
 92             }
 93         }
 94         for(int i=0;i<m;i++){
 95             if(i) printf(" ");
 96             printf("%d",ans[i]+1);
 97         }
 98         puts("");
 99     }
100     return 0;
101 }
View Code

 

G  The area http://acm.hdu.edu.cn/showproblem.php?pid=1071

给3个点,两点确定一条直线,三点确定二次函数的方程,分别求区间内的面积,积分,然后相减就是阴影面积。

 1 #include<cstdio>
 2 int main() {
 3     int t;
 4     double x1,x2,x3,y1,y2,y3;
 5     while(~scanf("%d",&t)) {
 6         while(t--) {
 7             scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3);
 8             double a2=(y3-y2)/(x3-x2);
 9             double b2=y2-a2*x2;
10             double a1=((y2-y1)/(x2-x1)-(y3-y1)/(x3-x1))/(x2-x3);
11             double b1=(y3-y1)/(x3-x1)-a1*(x3+x1);
12             double c1=y1-a1*x1*x1-b1*x1;
13             double s1=a1*x3*x3*x3/3+b1*x3*x3/2+c1*x3;
14             double h1=a1*x2*x2*x2/3+b1*x2*x2/2+c1*x2;
15             s1-=h1;
16             double s2=a2*x3*x3/2+b2*x3;
17             double h2=a2*x2*x2/2+b2*x2;
18             s2-=h2;
19             printf("%.2f\n",s1-s2);
20         }
21     }
22     return 0;
23 }
View Code

 

 E  Ping pong  http://acm.hdu.edu.cn/showproblem.php?pid=2492

用on的预处理出某一个位置之前几个比它小,几个它大,后面同理,前面小乘后面大的个数,是一种,前面大乘后面小的,是一种。预处理中要快速知道前面有几个比我小,那么可以用树状数组把on的求和降到logn。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define mt(a,b) memset(a,b,sizeof(a))
 4 typedef __int64 LL;
 5 const int M=100010;
 6 class One_Tree_Array { //一维树状数组
 7     typedef int typev;
 8     typev a[M];
 9 public:
10     void init() {
11         mt(a,0);
12     }
13     int lowb(int t) {
14         return t&(-t);
15     }
16     void add(int i,typev v) {
17         for(; i<M; a[i]+=v,i+=lowb(i));
18     }
19     typev sum(int i) {
20         typev s=0;
21         for(; i>0; s+=a[i],i-=lowb(i));
22         return s;
23     }
24 }gx;
25 int a[M],big[M],sma[M],prebig[M],presma[M];
26 int main(){
27     int t,n;
28     while(~scanf("%d",&t)){
29         while(t--){
30             scanf("%d",&n);
31             for(int i=1;i<=n;i++){
32                 scanf("%d",&a[i]);
33             }
34             gx.init();
35             for(int i=n;i>=1;i--){
36                 sma[i]=gx.sum(a[i]);
37                 big[i]=n-i-sma[i];
38                 gx.add(a[i],1);
39             }
40             gx.init();
41             for(int i=1;i<=n;i++){
42                 presma[i]=gx.sum(a[i]);
43                 prebig[i]=i-1-presma[i];
44                 gx.add(a[i],1);
45             }
46             LL ans=0;
47             for(int i=1;i<=n;i++){
48                 ans+=prebig[i]*sma[i];
49                 ans+=presma[i]*big[i];
50             }
51             printf("%I64d\n",ans);
52         }
53     }
54     return 0;
55 }
View Code

 当然可以掏出线段树来做树状数组的工作。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define mt(a,b) memset(a,b,sizeof(a))
 4 #define lrrt int L,int R,int rt
 5 #define iall 1,M-1,1
 6 #define imid int mid=(L+R)>>1
 7 #define lson L,mid,rt<<1
 8 #define rson mid+1,R,rt<<1|1
 9 typedef __int64 LL;
10 const int M=100010;
11 int tree[M<<2];
12 int a[M],big[M],sma[M],prebig[M],presma[M];
13 void pushup(int rt){
14     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
15 }
16 void update(int x,lrrt){
17     if(L==R){
18         tree[rt]++;
19         return ;
20     }
21     imid;
22     if(mid>=x) update(x,lson);
23     else       update(x,rson);
24     pushup(rt);
25 }
26 int query(int x,int y,lrrt){
27     if(x<=L&&R<=y) return tree[rt];
28     imid;
29     int ans=0;
30     if(mid>=x) ans+=query(x,y,lson);
31     if(mid<y)  ans+=query(x,y,rson);
32     return ans;
33 }
34 int main(){
35     int t,n;
36     while(~scanf("%d",&t)){
37         while(t--){
38             scanf("%d",&n);
39             for(int i=1;i<=n;i++){
40                 scanf("%d",&a[i]);
41             }
42             mt(tree,0);
43             for(int i=n;i>=1;i--){
44                 sma[i]=query(1,a[i],iall);
45                 big[i]=n-i-sma[i];
46                 update(a[i],iall);
47             }
48             mt(tree,0);
49             for(int i=1;i<=n;i++){
50                 presma[i]=query(1,a[i],iall);
51                 prebig[i]=i-1-presma[i];
52                 update(a[i],iall);
53             }
54             LL ans=0;
55             for(int i=1;i<=n;i++){
56                 ans+=prebig[i]*sma[i];
57                 ans+=presma[i]*big[i];
58             }
59             printf("%I64d\n",ans);
60         }
61     }
62     return 0;
63 }
View Code

 

 

A  Online Judge  http://acm.hdu.edu.cn/showproblem.php?pid=1073

模拟字符串比较

 1 #include<cstdio>
 2 #include<cstring>
 3 const int M=5010;
 4 char a[M][M],b[M][M],sa[M*M],sb[M*M],op[M];
 5 bool judge(char c) {
 6     if(c==' '||c=='\t'||c=='\n') return false;
 7     return true;
 8 }
 9 int main() {
10     int t;
11     while(~scanf("%d",&t)) {
12         getchar();
13         while(t--) {
14             gets(op);
15             int la=0;
16             while(gets(op)&&strcmp(op,"END")) {
17                 strcpy(a[la++],op);
18             }
19             gets(op);
20             int lb=0;
21             while(gets(op)&&strcmp(op,"END")) {
22                 strcpy(b[lb++],op);
23             }
24             if(la==lb) {
25                 bool flag=true;
26                 for(int i=0; i<la; i++) {
27                     if(strcmp(a[i],b[i])) {
28                         flag=false;
29                         break;
30                     }
31                 }
32                 if(flag) {
33                     puts("Accepted");
34                     continue;
35                 }
36             }
37             int lsa=0,lsb=0;
38             for(int i=0; i<la; i++) {
39                 for(int j=0; a[i][j]; j++) {
40                     if(judge(a[i][j])) {
41                         sa[lsa++]=a[i][j];
42                     }
43                 }
44             }
45             sa[lsa]=0;
46             for(int i=0; i<lb; i++) {
47                 for(int j=0; b[i][j]; j++) {
48                     if(judge(b[i][j])) {
49                         sb[lsb++]=b[i][j];
50                     }
51                 }
52             }
53             sb[lsb]=0;
54             if(!strcmp(sa,sb)) puts("Presentation Error");
55             else puts("Wrong Answer");
56         }
57     }
58     return 0;
59 }
View Code

 

 C Box of Bricks http://poj.org/problem?id=1477

水。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 const int M=1010;
 4 int a[M];
 5 int main(){
 6     int n,cas=1;
 7     while(~scanf("%d",&n),n){
 8         int sum=0;
 9         for(int i=0;i<n;i++){
10             scanf("%d",&a[i]);
11             sum+=a[i];
12         }
13         sum/=n;
14         int ans=0;
15         for(int i=0;i<n;i++){
16             ans+=abs(a[i]-sum);
17         }
18         printf("Set #%d\nThe minimum number of moves is %d.\n\n",cas++,ans/2);
19     }
20     return 0;
21 }
View Code

 

 

B X问题 http://acm.hdu.edu.cn/showproblem.php?pid=1573 

由于x%a=b  ai共10个,并且最大值是10,所以最小公倍数最大是2520,可以暴力。

 1 #include<cstdio>
 2 const int M=16;
 3 int a[M],b[M];
 4 int gcd(int a,int b) { //最大公约数
 5     return b?gcd(b,a%b):a;
 6 }
 7 int lcm(int a,int b) { //最小公倍数
 8     return a/gcd(a,b)*b;
 9 }
10 int main(){
11     int t,n,m;
12     while(~scanf("%d",&t)){
13         while(t--){
14             scanf("%d%d",&n,&m);
15             int sumlcm=1;
16             for(int i=0;i<m;i++){
17                 scanf("%d",&a[i]);
18                 sumlcm=lcm(sumlcm,a[i]);
19             }
20             for(int i=0;i<m;i++){
21                 scanf("%d",&b[i]);
22             }
23             int ans=-1;
24             for(int i=1;i<=sumlcm;i++){
25                 bool flag=true;
26                 for(int j=0;j<m;j++){
27                     if(i%a[j]!=b[j]){
28                         flag=false;
29                         break;
30                     }
31                 }
32                 if(flag){
33                     ans=i;
34                     break;
35                 }
36             }
37             if(ans==-1||ans>n){
38                 puts("0");
39                 continue;
40             }
41             int sum=(n-ans)/sumlcm+1;
42             printf("%d\n",sum);
43         }
44     }
45     return 0;
46 }
View Code

 也可以用不要求ai互质的中国剩余定理解模线性方程组。

 1 #include<cstdio>
 2 const int M=16;
 3 int a[M],b[M];
 4 int gcd(int a,int b) { //最大公约数
 5     return b?gcd(b,a%b):a;
 6 }
 7 int lcm(int a,int b) { //最小公倍数
 8     return a/gcd(a,b)*b;
 9 }
10 int ext_gcd(int a,int b,int &x,int &y) { //扩展gcd d=gcd(a,b)=a*x+b*y; return d,x,y;
11     int t,ret;
12     if(!b) {
13         x=1;
14         y=0;
15         return a;
16     }
17     ret=ext_gcd(b,a%b,x,y);
18     t=x;
19     x=y;
20     y=t-a/b*y;
21     return ret;
22 }
23 int modular_linear_system(int a[],int b[],int n){//求解模线性方程组(无要求)X mod a[i]=b[i],n个方程
24     int m1,m2,r1,r2,c,d,t,x,y;
25     m1=a[0];
26     r1=b[0];
27     for(int i=1;i<n;i++){
28         m2=a[i];
29         r2=b[i];
30         c=r2-r1;
31         d=ext_gcd(m1,m2,x,y);
32         if(c%d) return -1;
33         t=m2/d;
34         x=(c/d*x%t+t)%t;
35         r1=m1*x+r1;
36         m1=m1*m2/d;
37     }
38     return r1;
39 }
40 int main() {
41     int t,n,m;
42     while(~scanf("%d",&t)) {
43         while(t--) {
44             scanf("%d%d",&n,&m);
45             int sumlcm=1;
46             for(int i=0; i<m; i++) {
47                 scanf("%d",&a[i]);
48                 sumlcm=lcm(sumlcm,a[i]);
49             }
50             for(int i=0; i<m; i++) {
51                 scanf("%d",&b[i]);
52             }
53             int ans=modular_linear_system(a,b,m);
54             if(ans==-1||ans>n) {
55                 puts("0");
56                 continue;
57             }
58             if(ans==0) ans+=sumlcm;
59             int sum=(n-ans)/sumlcm+1;
60             printf("%d\n",sum);
61         }
62     }
63     return 0;
64 }
View Code

 

 

end

posted on 2014-08-22 22:45  gaolzzxin  阅读(191)  评论(0编辑  收藏  举报