CSU Monthly 2013 Aug

http://acm.csu.edu.cn/OnlineJudge/contest.php?cid=2036

A:

法一:

p = 0.a1a2a3...ak(b1b2...bm)
A = p*10^k = a1a2a3...ak.(b1b2...bm)
B = p*10^(k+m) = a1a2a3...akb1b2...bm.(b1b2...bm)

于是得B-A = p(10^(k+m)-10^(k))为整数
p =  (B-A)/(10^(k+m)-10^(k));
直接辗转相除 化为最简形式

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define LL long long
#define max(a,b)a>b?a:b
#define min(a,b)a<b?a:b
#define maxn 100000
#define maxm 100000
#define inf 999999
using namespace std;
 
char s[100];
char a[100];
char b[100];
LL gcd(LL m,LL n)
{
    return m%n==0?n:gcd(n,m%n);
}
 
int main()
{
    while(scanf("%s",s)!=-1)
    {
        int len = strlen(s);
        int k1;
        int k2;
        k1 = k2 = 0;
 
        for(int i=2;i<len && s[i]!='(';i++)
            a[k1++] = s[i];
        a[k1] = 0;
 
        for(int i=k1+3;i<len && s[i]!=')';i++)
        b[k2++] = s[i];
        b[k2] = 0;
 
        bool flag = 1;
        for(int i=0;i<k2;i++)
        {
            if(b[i]!='0'){
                flag = 0;
                break;
            }
        }
 
        if(flag){
 
            LL m = 1;
            LL ans = 0;
            for(int i=k1-1;i>=0;i--)
            {
                ans += m*(a[i]-48);
                m *= 10;
            }
 
            LL c = gcd(ans,m);
 
            printf("%lld/%lld\n",ans/c,m/c);
 
            continue;
        }
 
        LL m1 = 1;
        LL A = 0;
        for(int i=k1-1;i>=0;i--)
        {
            A += m1*(a[i]-48);
            m1*=10;
        }
 
        LL B = 0;
        LL m2 = 1;
        for(int i=k2-1;i>=0;i--)
        {
            B += m2*(b[i]-48);
            m2 *= 10;
        }
 
        for(int i=k1-1;i>=0;i--)
        {
            B += m2*(a[i]-48);
            m2*=10;
        }
 
        LL s = gcd(B-A,m2-m1);
 
        printf("%lld/%lld\n",(B-A)/s,(m2-m1)/s);
    }
    return 0;
}
View Code

法二:

 根据 0.(9)=1,按人工模拟的方法把小数化成分数,再化成最简分数.

#include"stdio.h"
#include"string.h"
#include"math.h"
char ch[20];
long long work(long long m,long long n)
{
    long long r;
    r=m%n;
    while(r!=0)
    {
        m=n;
        n=r;
        r=m%n;
    }
    return n;
}
int main()
{
    long long x,y,x1,y1;
    long long xx,yy;
    int i,j,l;
    while(scanf("%s",ch)!=EOF)
    {
        l=strlen(ch);
        int find=0;
        for(i=0; i<l; i++)
        {
            if(!(ch[i]=='0'||ch[i]=='.'||ch[i]=='('||ch[i]==')'))
            {
                find=1;
                break;
            }
        }
        if(find==0)
        {
            printf("0/1\n");
            continue;
        }
        int sum1,sum2;
        sum1=sum2=0;
        for(i=0; i<l; i++)
        {
            if(ch[i]=='.') continue;
            else if(ch[i]!='(')
            {
                sum1++;
            }
            else break;
        }
        sum2=l-sum1-3;
        xx=yy=0;
        for(i=sum1,j=1; i>=0; i--)
        {
            if(ch[i]=='.') continue;
            xx+=(int)(ch[i]-'0')*j;
            j*=10;
        }
        for(i=l-2,j=1; i>=0; i--,j*=10)
        {
            if(ch[i]=='(') break;
            yy+=(int)(ch[i]-'0')*j;
        }
        x1=pow(10,sum2)-1;
        i=0;
        while(ch[i]!='.'||ch[i]=='0') i++;
        y1=pow(10,sum1-i);
        if(yy==0)
        {
            x=xx;
            y=y1;
        }
        else
        {
                x=yy+xx*x1;
                y=x1*y1;
        }
        long long m,n;
        m=x;
        n=y;
        long long e;
        while(work(m,n)!=1)
        {
            e=work(m,n);
            m=m/e;
            n=n/e;
        }
        printf("%lld/%lld\n",m,n);
        getchar();
    }
    return 0;
}
 
/**************************************************************
    Problem: 1303
    User: wanglong306
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:980 kb
****************************************************************/
View Code

 

 

 

 

 

B Manor:

【模拟】时间O(M*N)。无压力。注意,求第m次操作前前前前的B中元素个数。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h>
 4 #define maxn 100010
 5  
 6 int n,m,a,b;
 7 int seq[maxn];
 8 int q;
 9  
10 int ans[222];
11 int main()
12 {
13     while (scanf("%d%d%d%d",&n,&m,&a,&b)==4)
14     {
15         int mm = 0;
16         int pos = 0;
17         ans[0] = 0;
18         for (int i=1;i<=n;i++){
19             scanf("%d",&seq[i]);
20             if (seq[i] > mm)
21             {
22                 mm = seq[i];
23                 pos = i;
24             }
25             if (seq[i] > m)
26             {
27                 ans[0]++;
28             }
29         }
30  
31         for (int i=1;i<=200;i++)
32         {
33             if (mm > m)
34             {
35                 seq[pos] = 0;
36             }
37             ans[i] = 0;
38             mm = 0;
39             pos = 0;
40             for (int j=1;j<=n;j++)
41             {
42                 if (seq[j]<=m){
43                     seq[j] += a;
44                 }else{
45                     seq[j] += b;
46                 }
47  
48                 if (seq[j] > m)
49                 {
50                     ans[i]++;
51                 }
52                 if (seq[j] > mm)
53                 {
54                     mm = seq[j];
55                     pos = j;
56                 }
57             }
58         }
59         scanf("%d",&q);
60         while (q--)
61         {
62             int p;
63             scanf("%d",&p);
64             printf("%d\n",ans[p-1]);
65         }
66     }
67     return 0;
68 }
69  
70 /**************************************************************
71     Problem: 1306
72     User: OUC_OptKernel
73     Language: C++
74     Result: Accepted
75     Time:640 ms
76     Memory:1356 kb
77     Author:wangsouc
78 ****************************************************************/
csu1306

C:凹凸曼和小怪兽的故事

 【乱搞】枚举一个集合中的位置,再另一个集合中求最短距离。分别对x,y排序,乱搞。目测都是随机数据?如果有手动数据,应该可以卡掉这种贪心的。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 #define LL long long
  6 #define max(a,b)a>b?a:b
  7 #define min(a,b)a<b?a:b
  8 #define maxn 100005
  9 #define maxm 100000
 10 #define inf 99999999999.0
 11 using namespace std;
 12  
 13 int n,a,b;
 14  
 15 struct da{
 16     int x,y;
 17 }A[maxn],B[maxn];
 18  
 19 bool cmp(da a,da b)
 20 {
 21     if(a.x == b.x) return a.y<b.y;
 22     return a.x<b.x;
 23 }
 24  
 25 bool cmp1(da a,da b)
 26 {
 27     if(a.y == b.y) return a.x<b.x;
 28     return a.y<b.y;
 29 }
 30  
 31  
 32  
 33 double get(int i,int j)
 34 {
 35     double x1 = (double)A[i].x;
 36     double x2 = (double)B[j].x;
 37     double y1 = (double)A[i].y;
 38     double y2 = (double)B[j].y;
 39  
 40     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
 41 }
 42  
 43 int find(int x)
 44 {
 45     if(x>B[n-1].x){
 46         return n-1;
 47     }else if(x<=B[0].x){
 48         return 0;
 49     }
 50  
 51     int l,r,mid;
 52  
 53     l = 0;r = n-1;
 54     while(r>l)
 55     {
 56         mid = (r+l)/2;
 57  
 58         if(B[mid].x == x){
 59             return mid;
 60         }else if(B[mid].x > x){
 61             r = mid;
 62         }else{
 63             l = mid+1;
 64         }
 65     }
 66  
 67     return r;
 68 }
 69  
 70 int find1(int y)
 71 {
 72     if(y>B[n-1].y){
 73         return n-1;
 74     }else if(y<=B[0].y){
 75         return 0;
 76     }
 77  
 78     int l,r,mid;
 79  
 80     l = 0;r = n-1;
 81     while(r>l)
 82     {
 83         mid = (r+l)/2;
 84  
 85         if(B[mid].y == y){
 86             return mid;
 87         }else if(B[mid].y > y){
 88             r = mid;
 89         }else{
 90             l = mid+1;
 91         }
 92     }
 93  
 94     return r;
 95 }
 96  
 97 int main()
 98 {
 99     while(scanf("%d%d%d",&n,&a,&b)!=-1)
100     {
101         for(int i=0;i<n;i++)
102         scanf("%d %d",&A[i].x,&A[i].y);
103         for(int i=0;i<n;i++)
104         scanf("%d %d",&B[i].x,&B[i].y);
105  
106         sort(B,B+n,cmp);
107  
108         double mi = inf;
109  
110         for(int i=0;i<n;i++)
111         {
112             int x = find(A[i].x);
113             for(int j=-5;j<5;j++)
114             {
115                 int s = x+j;
116                 if(s>=n || s<0) continue;
117  
118                 mi = min(get(i,s),mi);
119  
120             }
121  
122         }
123 /*
124         sort(B,B+n,cmp1);
125  
126         for(int i=0;i<n;i++)
127         {
128             int y = find1(A[i].y);
129             for(int j=-5;j<5;j++)
130             {
131                 int s = y + j;
132                 if(s>=n || s<0) continue;
133  
134                 mi = min(get(i,s),mi);
135  
136             }
137         }
138 */
139         printf("%.3lf\n",mi/(a+b));
140  
141     }
142     return 0;
143 }
144  
145 /**************************************************************
146     Problem: 1309
147     User: OUC_OptKernel
148     Language: C++
149     Result: Accepted
150     Time:32 ms
151     Memory:2540 kb
152     Author:S3_N
153 ****************************************************************/
csu1309

 

D:算是模拟题,比较复杂,因为数据范围不大,为了节省代码量,可以写的复杂一些。

需要注意的,以前出现的包括所有周的,

struct node
{
  string x;
  int y;
  int flag;
  int pre;
};
node a[20][205];
int num[20];
int n1;
int n ;
int found;
bool cmp(node a , node b)
{
  return  a.y > b.y;
}
void print()
{
  for(int i = 1; i <= 16; i ++ )
    printf("-");
}
int main()
{
  string s;
  n1 = 0 ;
  memset(num,0,sizeof(num));
  while(scanf("%d",&n) != EOF && n != 0 )
  {
    n1 ++ ;
    if(n1 != 1 )
    {
      num[n1] = num[n1-1];
      for(int i = 1 ; i <= num[n1] ; i ++ )
        a[n1][i] = a[n1 - 1][i];
    }
    for(int i = 1; i <= num[n1] ; i++ )
    {
      a[n1][i].y = 0 ;
      a[n1][i].flag = 0;
    }
    int y;
    for(int i = 1; i <= n ; i ++  )
    {
      cin >> s >> y ;
     // cout << y << endl;
      found = -1;
      for(int j = 1 ; j <= num[n1] ; j ++ )
      {
        if(a[n1][j].x == s)
        {
          found = j;
          break;
        }
      }
      if(found == - 1 )
      {
        num[n1] ++ ;
        a[n1][num[n1]].x = s ;
        a[n1][num[n1]].y = y;
        a[n1][num[n1]].flag = 3;
        a[n1][num[n1]].pre = 0;
      }
      else
      {
        a[n1][found].y = y;
        a[n1][found].pre = found;
      }
    }
    sort(a[n1] + 1 , a[n1] + num[n1] + 1 , cmp);
    int res;
    print();printf("WEEK %d",n1);print();printf("\n");
    for(int i = 1 ;i <= 5; i ++ )
    {
      printf("%d.",i);
      if(a[n1][i].flag == 3 ) printf("*NEW*   ");
      else if(a[n1][i].flag == 0)
      {
        if(a[n1][i].pre > i ) printf("*UP*    ");
        else
        if(a[n1][i].pre ==i)  printf("*STAY*  ");
        else                  printf("*DOWN*  ");
      }
      cout << a[n1][i].x << endl;
    }
  }
  return 0;
}
View Code

 

 

E:ZZY的宠物

【递推+矩阵乘法】记Fi,0<=i<=5是当前年龄为i的对数。Gi为下一个时刻对应年龄为i的对数。可写出递推公式:

G0 = 3*F1 + 2*F2 + 1*F3;Gi = Fi-1,i>=1.

然后矩阵乘法即可。

  1 #include<stdio.h>
  2 #include<math.h>
  3 #include<string.h>
  4 #define LL long long
  5 #define MOD 10000
  6  
  7 struct matrix{
  8     LL mat[6][6];
  9     void init(){
 10         memset(mat,0,sizeof(mat));
 11     }
 12     void mod()
 13     {
 14         for (int i=0;i<6;i++)
 15             for (int j=0;j<6;j++)
 16             {
 17                 mat[i][j] = (mat[i][j] % MOD + MOD) % MOD;
 18             }
 19         return ;
 20     }
 21     void EE()
 22     {
 23         init();
 24         for (int i=0;i<6;i++)
 25             mat[i][i] = 1;
 26         return ;
 27     }
 28  
 29 }M,E;
 30  
 31  
 32 void init()
 33 {
 34     M.init();
 35     M.mat[0][1] = 3;
 36     M.mat[0][2] = 2;
 37     M.mat[0][3] = 1;
 38     for (int i=1;i<6;i++)
 39         M.mat[i][i-1] = 1;
 40     return ;
 41 }
 42 matrix mul(matrix a,matrix b)
 43 {
 44     matrix c;
 45     c.init();
 46  
 47     for (int i=0;i<6;i++)
 48         for (int j=0;j<6;j++)
 49         {
 50             c.mat[i][j] = 0;
 51             for (int k=0;k<6;k++)
 52             {
 53                 c.mat[i][j] = ((c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % MOD + MOD) % MOD;
 54             }
 55         }
 56     c.mod();
 57     return c;
 58 }
 59 matrix power(matrix mm,LL n)
 60 {
 61     E.EE();
 62     while (n)
 63     {
 64         if (n %2 == 1)
 65         {
 66             E = mul(E,mm);
 67         }
 68         mm = mul(mm,mm);
 69         n /= 2;
 70     }
 71     return E;
 72 }
 73 LL solve(LL n)
 74 {
 75     LL res = 0;
 76     init();
 77     M = power(M,n);
 78     for (int i=0;i<6;i++)
 79     {
 80         res = (res + M.mat[i][0]) % MOD;
 81     }
 82     return res;
 83 }
 84  
 85 int main()
 86 {
 87     LL n;
 88     int cast = 0;
 89     while (scanf("%lld",&n)==1){
 90         LL  ans = solve(n);
 91         ans = (ans*2) % MOD;
 92         printf("Case %d: ",++cast);
 93         printf("%lld\n",ans);
 94     }
 95     return 0;
 96 }
 97  
 98 /**************************************************************
 99     Problem: 1313
100     User: OUC_OptKernel
101     Language: C++
102     Result: Accepted
103     Time:124 ms
104     Memory:964 kb
105     Author:wangsouc
106 ****************************************************************/
csu1313

F:ZZY的困惑

【枚举】数据较小直接枚举即可,时间O(2^m*m*n)。我写的dfs搜索。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 int n;
  5 int m;
  6 int seq[22];
  7 int mat[22][22];
  8 int sum[22];
  9 int ans;
 10 int p[22];
 11 int q[22];
 12 bool check(int tot)
 13 {
 14     memset(sum,0,sizeof(sum));
 15     for (int i=1;i<=tot;i++)
 16     {
 17         int u = p[i];
 18         for (int j=1;j<=n;j++)
 19             sum[j] += mat[u][j];
 20     }
 21     for (int i=1;i<=n;i++)
 22         if (sum[i] < seq[i])
 23             return false;
 24     return true;
 25 }
 26 void dfs(int deep,int tot)
 27 {
 28     if (deep > m)
 29     {
 30         if (!check(tot))
 31             return ;
 32  
 33         if (tot == ans)
 34         {
 35             int flag = 0;
 36             for (int i=1;i<=tot;i++){
 37                 if (p[i] == q[i]){
 38                     continue;
 39                 }
 40                 if (p[i] < q[i]){
 41                     flag = 1;
 42                 }else{
 43                     flag = 0;
 44                 }
 45                 break;
 46             }
 47             if (flag)
 48             {
 49                 for (int i=1;i<=tot;i++)
 50                 {
 51                     q[i] = p[i];
 52                 }
 53             }
 54  
 55         }
 56         if (tot > ans)
 57         {
 58             ans = tot;
 59             for (int i=1;i<=tot;i++)
 60                 q[i] = p[i];
 61         }
 62         return ;
 63     }
 64     p[tot+1] = deep;
 65     dfs(deep+1,tot+1);
 66     dfs(deep+1,tot);
 67     return ;
 68 }
 69 int main()
 70 {
 71     while (scanf("%d",&n)==1)
 72     {
 73         for (int i=1;i<=n;i++)
 74             scanf("%d",&seq[i]);
 75         scanf("%d",&m);
 76         for (int i=1;i<=m;i++)
 77         {
 78             for (int j=1;j<=n;j++)
 79                 scanf("%d",&mat[i][j]);
 80         }
 81         ans = 0;
 82         dfs(1,0);
 83  
 84         printf("%d",ans);
 85         for (int i=1;i<=ans;i++)
 86         {
 87             printf(" %d",q[i]);
 88         }
 89         printf("\n");
 90     }
 91     return 0;
 92 }
 93  
 94 /**************************************************************
 95     Problem: 1314
 96     User: OUC_OptKernel
 97     Language: C++
 98     Result: Accepted
 99     Time:104 ms
100     Memory:964 kb
101     Author:wangsouc
102 ****************************************************************/
csu1314

G:

【排序贪心】签到题,呵呵。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <cassert>
 7 #include <iostream>
 8 #include <sstream>
 9 #include <fstream>
10 #include <map>
11 #include <set>
12 #include <vector>
13 #include <queue>
14 #include <algorithm>
15 #include <iomanip>
16 using namespace std;
17  
18 #define abs(x) ((x)>=0?(x):-(x))
19 #define i64 long long
20 #define u32 unsigned int
21 #define u64 unsigned long long
22 #define clr(x,y) memset(x,y,sizeof(x))
23 #define PI acos(-1.0)
24 #define sqr(x) ((x)*(x))
25 #define maxn 100
26 struct node
27 {
28   int t,id;
29 };
30 node a[maxn];
31 int n ;
32 bool cmp(node t1,node t2)
33 {
34   if(t1.t != t2.t) return t1.t < t2.t;
35   else return t1.id < t2.id;
36 }
37 int main()
38 {
39   while(scanf("%d",&n)!=EOF)
40   {
41     for(int i = 1 ; i <= n; i ++ )
42     {
43       scanf("%d",&a[i].t);
44       a[i].id = i;
45     }
46     sort(a + 1 ,a + n + 1 ,cmp);
47     int sum1,sum2,base;
48     base = 0 ;
49     sum1 = 0 ;
50     sum2 = 0 ;
51     for(int i = 1; i <= n ; i ++ )
52     {
53       base += a[i].t;
54       if(base > 300 ) break;
55       sum1 ++ ;
56       sum2 += base;
57     }
58     printf("%d %d\n",sum1,sum2);
59     for(int i = 1; i <= sum1 ; i++ )
60       printf("%d\n",a[i].id);
61   }
62   return 0;
63 }
64  
65 /**************************************************************
66     Problem: 1315
67     User: OUC_OptKernel
68     Language: C++
69     Result: Accepted
70     Time:4 ms
71     Memory:1484 kb
72     Author:jh8180129
73 ****************************************************************/
csu1315

 

H:协会的账目

题意:给一个序列,三种操作,在原序列的某个数后面插入一个数,如果之前有数了,那么插在这些数最后,两种查询,第一种查询,查询 最大的相邻的插值, 查询 最接近的两个数的差值。

只有插入没有删除,每次插入,会破坏一个关系,增加两个关系,并且破坏的关系只与原序列的每个数后面插入形成的小序列的头跟尾相关。第一种询问,维护一个最大堆即可,每次查询直接输出最大的即可,但为了方便删除,维护一个set也可以。第二个查询,直接维护这些数,每次添加一个新的数,查询这个集合中与该数最接近的两个数判断即可。

注意可能会有重复元素,维护multiset。

【multiset维护】:对于两种询问,维护两个multiset。求相邻差值最大,维护所有的相邻数的差值,对于插入一个数,破坏一组相邻关系,在集合中删除,会再增加两个关系,在集合中增加,直接查找集合最后元素即可。第二个操作,保留当前的最小值,即答案,每次增加数,在集合中查找与之最接近的数再判断更新答案即可,然后插入。每次插入,只需知道每个账目最后的收支金额和下一个账目的第一个收支金额,分别记录即可。

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <ctime>
  6 #include <cassert>
  7 #include <iostream>
  8 #include <sstream>
  9 #include <fstream>
 10 #include <map>
 11 #include <set>
 12 #include <vector>
 13 #include <queue>
 14 #include <algorithm>
 15 #include <iomanip>
 16 using namespace std;
 17  
 18 #define abs(x) ((x)>=0?(x):-(x))
 19 #define i64 long long
 20 #define u32 unsigned int
 21 #define u64 unsigned long long
 22 #define clr(x,y) memset(x,y,sizeof(x))
 23 #define PI acos(-1.0)
 24 #define sqr(x) ((x)*(x))
 25 #define maxn 500100
 26 #define pii pair<int,int>
 27 #define inf 0x7ffffff
 28  
 29 int head[maxn];
 30 int tail[maxn];
 31 int que[2*maxn];
 32 int n,m;
 33 int _l1;
 34 int cnt;
 35  
 36 multiset<int> mp,mp1;
 37 multiset<int>::iterator iter,it1;
 38  
 39 int get(int x )
 40 {
 41   int res ;
 42   iter = mp.lower_bound(x);
 43   it1 = iter;
 44   if(iter == mp.end())
 45   {
 46     --iter;
 47     return abs(*iter - x);
 48   }
 49   iter = it1;
 50   if(iter == mp.begin())
 51   {
 52     res = abs(*iter - x);
 53     iter ++ ;
 54     if(iter != mp.end())
 55       res = min(res , abs( *iter - x ) ) ;
 56     return res;
 57   }
 58   iter = it1;
 59   res = abs(*iter - x ) ;
 60   iter ++ ;
 61   if(iter != mp.end())
 62     res = min(res , abs(*iter - x ));
 63   iter -- ;
 64   iter -- ;
 65   res = min(res , abs(*iter - x ));
 66   return res;
 67 }
 68 void update(int id,int x )
 69 {
 70   int x1 ,x2 ,tmp;
 71   x1 = que[tail[id]];
 72   if(id < n ) x2 = que[head[id+1]];
 73   if(id < n )
 74   {
 75     tmp = abs(x1 - x2);
 76     iter = mp1.find(tmp);
 77     mp1.erase(iter);
 78   }
 79   mp1.insert(abs(x - x1));
 80   if(id < n  ) mp1.insert(abs(x-x2));
 81   que[++cnt] = x;
 82   tail[id] = cnt;
 83 }
 84 char str[105];
 85 int main()
 86 {
 87   while (scanf("%d%d",&n,&m) != EOF)
 88   {
 89     mp.clear();
 90     mp1.clear();
 91     _l1 = inf;
 92     int tmp ;
 93     for (int i=1; i<=n; i++)
 94     {
 95       head[i] = i;
 96       tail[i] = i;
 97       scanf("%d",&que[i]);
 98       if(i > 1 )
 99       {
100         mp1.insert(abs(que[i]-que[i-1]));
101       }
102       if(mp.size() > 0 )
103       {
104         tmp = get(que[i]);
105         if(tmp < _l1)
106           _l1 = tmp;
107       }
108       mp.insert(que[i]);
109     }
110     cnt = n ;
111     int id , x;
112     while (m--)
113     {
114       scanf("%s",str);
115       if (str[0] == 'I' && str[1]=='n')
116       {
117         scanf("%d%d",&id,&x);
118         update(id,x);
119         if(mp.size() > 0 )
120         {
121           tmp = get(x);
122           if(tmp < _l1)
123             _l1 = tmp;
124         }
125         mp.insert(x);
126       }
127       else if (str[0] == 'M' && str[1] =='i')
128       {
129         printf("%d\n",_l1);
130       }
131       else if ( str[0] == 'M' && str[1]=='a')
132       {
133        // for(iter = mp1.begin() ; iter != mp1.end(); iter ++ )
134        //{
135          // printf("%d ",*iter);
136       //  }
137        // printf("\n");
138         iter = mp1.end();
139         --iter;
140         printf("%d\n", *iter);
141       }
142     }
143   }
144   return 0;
145 }
146  
147 /**************************************************************
148     Problem: 1316
149     User: OUC_OptKernel
150     Language: C++
151     Result: Accepted
152     Time:400 ms
153     Memory:15636 kb
154     Author:jh8180129
155 ****************************************************************/
csu1316

 

I:

题意:给定一个图,题目中的信息说明是一棵树,然后求最远的两个点之间的距离,注意有负权,如果全部为负权,那直接输出最大的值即可。

树形DP ,求直径,还可以两次dfs,比赛时候没想起是求直径,直接写dp了,还好代码不多。

直接遍历一边即可。假设以1为根。以u为根的子树,dfs后记录下子树中节点到u的最大值res1,和次大值res2(注意是不同分支中的),然后判断即可。答案在这些中 

max(res1 , res2 ,res1 + res2 ),对每个遍历一遍,再判断一下全部是负权的情况。

#define maxn 50005
#define inf 0x3fffffffffffffff
struct node
{
  int v,next;
  long long w ;
};
node e[maxn * 2 ];
int cnt ;
int head[maxn];
long long dp[maxn][2];
void init()
{
  cnt = 0;
  memset(head,-1,sizeof(head));
}

void add(int u,int v,int w)
{
  e[cnt].v = v ;
  e[cnt].w = w;
  e[cnt].next = head[u];
  head[u] = cnt ++ ;

  e[cnt].v = u ;
  e[cnt].w = w ;
  e[cnt].next = head[v] ;
  head[v] = cnt ++ ;

  return  ;
}
long long ans;
long long dfs(int u ,int fa )
{
  int sons;
  long long res1 , res2 ;
  long long tmp ;
  res1 = res2 = -inf ;
  sons = 0 ;
  for(int i = head[u]; i != -1 ; i = e[i].next)
  if(e[i].v != fa )
  {
    sons ++ ;
    tmp = e[i].w + dfs(e[i].v,u);
    if(tmp > res1)
    {
      res2 = res1;
      res1 = tmp;
    }
    else if(tmp > res2)
    {
      res2 = tmp;
    }
  }
  if(sons == 1 )
  {
    ans = max(ans , res1);
  }
  else
  {
    ans = max(ans , res1 + res2);
    ans = max(ans , res1);
  }
  return max(0LL,res1);
}
int main()
{
  long long _max;
  int n,m;
  while(scanf("%d%d",&n,&m)!=EOF)
  {
    init();
    if(m != n - 1 )
    {
      while(1 == 1 )
      {
        int a ;
        a = 1 ;
      }
    }
    int u,v;
    long long w;
    _max = -inf ;
    for(int i = 1; i <= m  ;i ++ )
    {
      scanf("%d%d%lld",&u,&v,&w);
      add(u,v,w);
      _max = max(w,_max);
    }
    //printf("%lld\n",_max);
    long long tmp;
    ans = -inf ;
    tmp = dfs(1,0);
   // ans = max(ans , tmp );
    ans = max(ans , _max);
    printf("%lld\n",ans);
  }
    return 0;
}
View Code

 

J:

【二分+最短路】题意求最大值最小,二分答案再求解即可。数据较大,使用spfa或者dij+堆。我写的spfa。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<math.h>
  5 #define maxn 2020
  6 #define maxm 50500
  7  
  8 struct edge{
  9     int u;
 10     int v;
 11     int val;
 12     int next;
 13 }e[2*maxm],seq[maxm];
 14 int last[maxn];
 15 int tot;
 16 int n,m;
 17 int A,B;
 18 #define inf 100000000
 19  
 20 void add(int u,int v,int val)
 21 {
 22     e[tot].v = v;
 23     e[tot].val = val;
 24     e[tot].next = last[u];
 25     last[u] = tot++;
 26     return ;
 27 }
 28 void build(int val)
 29 {
 30     memset(last,-1,sizeof(last));
 31     tot = 0;
 32     for (int i=1;i<=m;i++)
 33     {
 34         if (seq[i].val <= val)
 35         {
 36             add(seq[i].u,seq[i].v,seq[i].val);
 37             add(seq[i].v,seq[i].u,seq[i].val);
 38         }
 39     }
 40     return ;
 41 }
 42 int que[maxm];
 43 int dis[maxn];
 44 bool vis[maxn];
 45  
 46 int spfa()
 47 {
 48     memset(vis,0,sizeof(vis));
 49     for (int i=1;i<=n;i++)
 50     {
 51         dis[i] = inf;
 52     }
 53     int head = 0, tail = 0;
 54     que[++tail] = A;
 55     vis[A] = 1;
 56     dis[A] = 0;
 57     while (head < tail)
 58     {
 59         int u = que[++head];
 60         for (int j=last[u];j!=-1;j=e[j].next)
 61         {
 62             int v = e[j].v;
 63             int val = e[j].val;
 64             if (dis[u] + val < dis[v])
 65             {
 66                 dis[v] = dis[u] + val;
 67                 if (vis[v]==0)
 68                 {
 69                     vis[v] = 1;
 70                     que[++tail] = v;
 71                 }
 72             }
 73         }
 74         vis[u] = 0;
 75     }
 76     if (dis[B] < inf)
 77         return dis[B];
 78     return -1;
 79 }
 80 int solve()
 81 {
 82     int res = -1;
 83     int l = 1, r = 10000;
 84     while (l <= r)
 85     {
 86         int mid = (l + r)/2;
 87         build(mid);
 88         int tmp = spfa();
 89         if (tmp == -1)
 90         {
 91             l = mid + 1;
 92         }else{
 93             res = tmp;
 94             r = mid - 1;
 95         }
 96     }
 97     return res;
 98 }
 99 int main()
100 {
101     while (scanf("%d%d%d%d",&n,&m,&A,&B)==4)
102     {
103         for (int i=1;i<=m;i++)
104         {
105             scanf("%d%d%d",&seq[i].u,&seq[i].v,&seq[i].val);
106         }
107         int ans = solve();
108         printf("%d\n",ans);
109     }
110     return 0;
111 }
112  
113 /**************************************************************
114     Problem: 1307
115     User: OUC_OptKernel
116     Language: C++
117     Result: Accepted
118     Time:44 ms
119     Memory:3544 kb
120 ****************************************************************/
csu1317

 

/******

OUC_OptKernel:首次AK,纪念。

******/

 

转载于:https://www.cnblogs.com/oucacm/articles/3293436.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值