The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest

 

打网络赛

比赛前的准备工作要做好

确保 c++/java/python的编译器能用

打好模板,放在桌面

 

A. PERFECT NUMBER PROBLEM

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <queue>
10 #include <iostream>
11 using namespace std;
12 
13 #define ll long long
14 
15 const int maxn=1e8+10;
16 const int inf=1e9;
17 const double eps=1e-8;
18 
19 int sum[maxn];
20 
21 int main()
22 {
23     int n=100000000,i,j;
24     for (i=1;i<n;i++)
25         for (j=i;j<n;j+=i)
26             sum[j]+=i;
27     for (i=1;i<n;i++)
28         if (sum[i]==i+i)
29             printf("%d ",i);
30     return 0;
31 }
32 /*
33 6 28 496 8128 33550336
34 Process returned 0 (0x0)   execution time : 24.646 s
35 */

 

较差的打表方法

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <queue>
10 #include <iostream>
11 using namespace std;
12 
13 #define ll long long
14 
15 const int maxn=1e4+10;
16 const int inf=1e9;
17 const double eps=1e-8;
18 
19 
20 
21 int main()
22 {
23     ///我相信很大一部分同学是网上找答案的,这不好
24 //    printf("6\n28\n496\n8128\n33550336");
25     ll sum,i,j,k;
26     for (i=1;i<=1000000000;i++)
27     {
28         sum=0;
29         k=sqrt(i);
30         for (j=1;j<=k;j++)
31             if (i%j==0)
32                 sum+=j+i/j;
33         if (k*k==i)
34             sum-=i;
35         sum-=i;
36         if (sum==i)
37             printf("%d ",i);
38         if (i%1000000==0)
39             printf("i=%d\n",i);
40     }
41     return 0;
42 }
43 /*
44 6 28 496 8128 33550336
45 18 min
46 */

 

C. Angry FFF Party

fib(x) 逐渐变得很大

而fib(fib(x))更是如此,

感觉可以打表

于是用python打表验证一下

 1 import math
 2 
 3  4 
 5 a=1/math.sqrt(5)
 6 
 7 b=(1+math.sqrt(5))/2
 8 
 9 c=(1-math.sqrt(5))/2
10 
11 a
12 
13 0.4472135954999579
14 
15 a
16 
17 for n in range(1,16):
18 
19     print(n)
20 
21     x=a*(pow(b,n) - pow(c,n))
22 
23     x=round(x)
24 
25     print(x)
26 
27 28 
29     y=a*(pow(b,x) - pow(c,x))
30 
31     print(y)
32 
33     print()
34 
35 1
36 1
37 1.0
38 
39 2
40 1
41 1.0
42 
43 3
44 2
45 1.0
46 
47 4
48 3
49 2.0
50 
51 5
52 5
53 5.000000000000001
54 
55 6
56 8
57 21.000000000000004
58 
59 7
60 13
61 233.00000000000006
62 
63 8
64 21
65 10946.000000000007
66 
67 9
68 34
69 5702887.0000000065
70 
71 10
72 55
73 139583862445.00024
74 
75 11
76 89
77 1.7799794160047194e+18
78 
79 12
80 144
81 5.555654042242954e+29
82 
83 13
84 233
85 2.2112364063039317e+48
86 
87 14
88 377
89 2.746979206949977e+78
90 
91 15
92 610
93 1.3582369791278544e+127

 

开始用java写 BigInteger

  1 import java.math.BigInteger;
  2 import java.util.Scanner;
  3 
  4 public class Main {
  5     static class mat {
  6         BigInteger [][]a=new BigInteger[2][2];
  7         mat() {
  8             a[0][0]=a[0][1]=a[1][0]=a[1][1]=BigInteger.ZERO;
  9         }
 10         static mat mul(mat a,mat b) {
 11             mat c=new mat();
 12             for (int k=0;k<2;k++)
 13                 for (int i=0;i<2;i++)
 14                     for (int j=0;j<2;j++)
 15                         c.a[i][j]=c.a[i][j].add(a.a[i][k].multiply(b.a[k][j]));
 16             return c;
 17         }
 18         void print() {
 19             for (int i=0;i<2;i++) {
 20                 for (int j=0;j<2;j++)
 21                     System.out.print(a[i][j]+" ");
 22                 System.out.println();
 23             }
 24             System.out.println();
 25         }
 26     }
 27     
 28     static BigInteger _pow(int n) {
 29         mat a=new mat();
 30         mat b=new mat();
 31         a.a[0][0]=BigInteger.ONE;
 32         a.a[0][1]=BigInteger.ZERO;
 33         a.a[1][0]=BigInteger.ZERO;
 34         a.a[1][1]=BigInteger.ONE;
 35         
 36         b.a[0][0]=BigInteger.ONE;
 37         b.a[0][1]=BigInteger.ONE;
 38         b.a[1][0]=BigInteger.ONE;
 39         b.a[1][1]=BigInteger.ZERO;
 40 
 41         while (n>0) {
 42             if (n%2==1)
 43                 a=mat.mul(a,b);
 44             b=mat.mul(b,b);
 45 //            b.print();
 46             n>>=1;
 47         }
 48         return a.a[1][0];
 49     }
 50     
 51     public static void main(String[] args) throws Exception {
 52         
 53         int i,len=100000;//10
 54         int []a=new int[100];
 55         BigInteger []b=new BigInteger[100];
 56         StringBuffer s=new StringBuffer("1");
 57         for (i=0;i<len;i++)
 58             s=s.append("0");
 59         String ss=new String(s);
 60         BigInteger maxb=new BigInteger(ss);
 61 //        System.out.println(maxb);
 62         
 63 //        _pow(10);
 64         
 65         a[1]=a[2]=1;
 66         mat ma = new mat();
 67         for (i=1;i<100;i++) {
 68             if (i<3)
 69                 a[i]=1;
 70             else
 71                 a[i]=a[i-1]+a[i-2];
 72 //            System.out.println(a[i]);
 73             b[i]=_pow(a[i]);
 74 //            if (i<10)
 75 //                System.out.println(b[i]);
 76             if (b[i].compareTo(maxb)>=0)
 77                 break;
 78         }
 79 //        System.out.println("i="+i);
 80         int maxg=i;
 81         
 82         Scanner in=new Scanner(System.in);
 83         int t=in.nextInt();
 84         BigInteger m;
 85         
 86         int []num=new int[100];
 87             int g=0;
 88             BigInteger[] bb=new BigInteger[11];
 89             for (i=0;i<=10;i++)
 90                 bb[i]=new BigInteger(Integer.toString(i));
 91             String []pr=new String[11];
 92             
 93         /*
 94         1 1 1 2 5 21
 95         */
 96             pr[1]="1";
 97             pr[2]="1 2";
 98             pr[3]="1 2 3";
 99             pr[4]="1 2 4";
100             pr[5]="1 2 3 4";
101             for (i=6;i<=10;i++)
102                 pr[i]=pr[i-5]+" 5";
103             
104         while (t-->0) {
105             m=in.nextBigInteger();
106             
107             g=0;
108             if (m.compareTo(bb[10])>0) {
109                 for (i=maxg;i>5;i--)
110                     if (m.compareTo(b[i])>=0) {
111                         m=m.subtract(b[i]);
112                         g=g+1;
113                         num[g]=i;
114                     }
115             }
116             if (m.compareTo(bb[10])>0)
117                 System.out.println(-1);
118             else {                
119                 for (i=1;i<=10;i++)
120                     if (m.compareTo(bb[i])==0)
121                         System.out.print(pr[i]);
122                 if (m.compareTo(bb[0])!=0 && g!=0)
123                     System.out.print(" ");
124                 if (g==0)
125                     System.out.println();
126                 for (i=g;i>=1;i--) {
127                     System.out.print(num[i]);
128                     if (i==1)
129                         System.out.println();
130                     else
131                         System.out.print(" ");
132                 }
133             }
134         }
135     }
136 }
137 /*
138 1 1 1 2 5 21
139 
140 1
141 1
142 1
143 2
144 5
145 21
146 233
147 10946
148 5702887
149 
150 100
151 1-10
152 11
153 21
154 27
155 */

 

H. Coloring Game

 

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <queue>
10 #include <iostream>
11 using namespace std;
12 
13 #define ll long long
14 
15 const int maxn=1e4+10;
16 const int inf=1e9;
17 const double eps=1e-8;
18 const ll mod=1e9+7;
19 
20 ll mul(ll a,ll b)
21 {
22     ll y=1;
23     while (b)
24     {
25         if (b&1)
26             y=y*a%mod;
27         a=a*a%mod;
28         b>>=1;
29     }
30     return y;
31 }
32 
33 int main()
34 {
35     int n;
36     scanf("%d",&n);
37     if (n==1)
38         printf("1");
39     else
40         printf("%lld",mul(3,n-2)*4%mod);
41     return 0;
42 }
43 /*
44 1000000000
45 */

 

K. MORE XOR

找规律

推公式较为复杂,据说用插板法

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <iostream>
using namespace std;

#define ll long long

const int maxn=1e5+10;
const int inf=1e9;
const double eps=1e-8;

int f[4][maxn],a[maxn];

int main()
{
//    printf("%d",1^2^5^6^9^10);
    int T,n,q,i,j,k,x,y,s,t,v;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        for (i=1;i<=n;i++)
            scanf("%d",&a[i]);

        for (k=0;k<4;k++)
            for (i=(k==0)?4:k,j=1;i<=n;i+=4,j++)
                f[k][j]=f[k][j-1]^a[i];

        scanf("%d",&q);
        while (q--)
        {
            scanf("%d%d",&i,&j);
            y=(j-i+1)%4;
            if (y==1)
            {
                ///i,i+4,i+8 ...
                x=i%4;
                s=(i+3)/4;
                t=s+(j-i)/4;
                printf("%d\n",f[x][t]^f[x][s-1]);
            }
            else if (y==2)
            {
                x=i%4;
                s=(i+3)/4;
                t=s+(j-i)/4;
                v=f[x][t]^f[x][s-1];

                i++;
                x=i%4;
                s=(i+3)/4;
                t=s+(j-i)/4;
                printf("%d\n",v^f[x][t]^f[x][s-1]);
            }
            else if (y==3)
            {
                i++;
                x=i%4;
                s=(i+3)/4;
                t=s+(j-i)/4;
                printf("%d\n",f[x][t]^f[x][s-1]);
            }
            else
                printf("0\n");
        }
    }
    return 0;
}
/*
1
10
1 2 3 4 5 6 7 8 9 10
100
1 7
*/

 

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <queue>
10 #include <iostream>
11 using namespace std;
12 
13 #define ll long long
14 
15 const int maxn=1e4+10;
16 const int inf=1e9;
17 const double eps=1e-8;
18 
19 int n=10;
20 
21 struct node
22 {
23     int a[30];
24     node operator+(const node &y)
25     {
26         node z;
27         for (int i=1;i<=n;i++)
28             z.a[i]=a[i]+y.a[i];
29         return z;
30     }
31 }f[4][30][30];
32 
33 int main()
34 {
35     int i,j,k,l;
36     int x=3;
37     for (i=1;i<=n;i++)
38         f[0][i][i].a[i]=1;
39     for (l=1;l<=x;l++)
40     {
41 //        for (i=1;i<n;i++)
42 //        {
43 //            f[l][i][i]=f[l-1][i][i];
44 //            for (j=i+1;j<=n;j++)
45 //                f[l][i][j]=f[l][i][j-1]+f[l-1][j][j];
46 //        }
47 
48         for (i=1;i<=n;i++)
49             for (j=i;j<=n;j++)
50             {
51                 if (i!=j)
52                     f[l][i][j]=f[l][i][j-1];
53                 for (k=i;k<=j;k++)
54                     f[l][i][j]=f[l][i][j]+f[l-1][k][j];
55             }
56     }
57     int y=3;
58     for (i=1;i<=n;i++)
59     {
60         for (j=1;j<=n;j++)
61 //            printf("%d%c",f[y][1][i].a[j],j==n?'\n':' ');
62             printf("%d%c",f[y][1][i].a[j] &1,j==n?'\n':' ');
63     }
64     return 0;
65 }
66 /*
67 1 0 0 0 0 0 0 0 0 0
68 1 1 0 0 0 0 0 0 0 0
69 0 1 0 0 0 0 0 0 0 0
70 0 0 0 0 0 0 0 0 0 0
71 1 0 0 0 1 0 0 0 0 0
72 1 1 0 0 1 1 0 0 0 0
73 0 1 0 0 0 1 0 0 0 0
74 0 0 0 0 0 0 0 0 0 0
75 1 0 0 0 1 0 0 0 1 0
76 1 1 0 0 1 1 0 0 1 1
77 
78 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
79 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
80 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
81 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
82 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
83 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
84 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
86 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
87 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0
88 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0
89 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
90 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0
91 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 0 0
92 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0
93 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
94 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0
95 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
96 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0
97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
98 */

 

 

M. Subsequence

序列自动机

非正统的写法:

1.从后往前,记录每一个字符最新出现的位置

2.贪心,找到第一个字符,在第一个字符位置之后找第二个字符,...

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <set>
 8 #include <map>
 9 #include <queue>
10 #include <iostream>
11 using namespace std;
12 
13 #define ll long long
14 
15 const int maxn=1e5+10;
16 const int inf=1e9;
17 const double eps=1e-8;
18 
19 int f[maxn][128],pre[maxn];
20 char s[maxn];
21 
22 int main()
23 {
24     int i,j,len,t;
25     memset(pre,0xff,sizeof(pre));
26     s[0]='a';
27     scanf("%s",s+1);
28     len=strlen(s+1);
29     for (i=len;i>=0;i--)
30     {
31         for (j=0;j<128;j++)
32             f[i][j]=pre[j];
33         pre[s[i]]=i;
34     }
35     scanf("%d",&t);
36     while (t--)
37     {
38         scanf("%s",s);
39         len=strlen(s);
40         j=f[0][s[0]];
41         for (i=1;i<len;i++)
42         {
43             if (j==-1)
44                 break;
45             j=f[j][s[i]];
46         }
47         if (j!=-1)
48             printf("YES\n");
49         else
50             printf("NO\n");
51     }
52     return 0;
53 }
54 /*
55 
56 */

 

C. Angry FFF Party

数位dp

原来的数据是完全无用的,
只需要火柴棒总数保持一致,
只需要对于每一位,火柴棒加的次数完全一样

不用考虑前导0
+0 -> +9
-0  -> +5

w为数字的位数,y使用的火柴数
f[w][y] 的最大值
f[w][y]=max(f[w-1][y-g[i]]+i*10^(w-1))    i=0..9
w<10,y<w*7+2

-11..1 无法改变
f[1][3]=-1
f[p][p*2+1]=-11..1
其它时候不用减法(至少可以节省一根火柴,使负号变为加号)
这个不成立,在第一个数时(潜在加法)
预处理

对于当前的前x个数字,y为使用的火柴棒总数,以此最大的值
对于第x个数字,位数为w
a[x][y]=max(a[x-1][z]+f[w][z-y])
x<=50,y<=7*50+2*49=448
[49个加号,50个数]


易错点:
+/- 不能单独每一位,而要整体求

 

正确通过 2019-04-21 00:57 5ms 448kB c++14
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <set>
  8 #include <map>
  9 #include <queue>
 10 #include <iostream>
 11 using namespace std;
 12 
 13 #define ll long long
 14 
 15 const int maxn=1e4+10;
 16 const int inf=1e9;
 17 const double eps=1e-8;
 18 
 19 /**
 20 其实最多只有9位,
 21 是小于10^9,没有等于
 22 
 23 999999999+999999999+...
 24 超过int
 25 **/
 26 
 27 int g[10]={6,2,5,5,4,5,6,3,7,6};
 28 int f[12][100];
 29 int mul[12];
 30 ll a[51][500];
 31 int fv[12];
 32 int add[128];
 33 char s[110];
 34 
 35 int main()
 36 {
 37     bool vis;
 38     int i,j,k,l,maxw,w,t,n,tot,sum,c;
 39 
 40 //    printf("%d\n",'+');///43
 41 //    printf("%d\n",'-');///45
 42     add[43]=2,add[45]=1;
 43     for (i=48;i<48+10;i++)
 44         add[i]=g[i-48];
 45 
 46     mul[1]=1;
 47     for (i=2;i<=9;i++)
 48         mul[i]=mul[i-1]*10;
 49 
 50     fv[1]=-1;
 51     for (i=2;i<=9;i++)
 52         fv[i]=fv[i-1]*10-1;
 53 
 54     memset(f,0x8f,sizeof(f));
 55     f[0][2]=0;///+
 56     for (i=1;i<=10;i++)
 57     {
 58         maxw=(i-1)*7+2;
 59         for (j=0;j<=maxw;j++)
 60             for (l=0;l<=9;l++)  ///或者只要用火柴数在一个数量时最大的数即可
 61                 f[i][j+g[l]]=max(f[i][j+g[l]],f[i-1][j]+l*mul[i]);
 62     }
 63 
 64     scanf("%d",&t);
 65     while (t--)
 66     {
 67         memset(a,0x8f,sizeof(a));
 68         scanf("%d",&n);
 69         scanf("%s",s);
 70         tot=0;
 71         vis=0;
 72         sum=0;
 73         a[0][0]=0;
 74         i=0;
 75         c=0;
 76         for (w=0;w<=n;w++)
 77         {
 78             tot+=add[s[w]];
 79             if (s[w]=='+' || s[w]=='-' || w==n)
 80             {
 81                 c++;
 82                 maxw=i*7+2;
 83                 for (j=0;j<=sum;j++)
 84                     for (k=0;k<=maxw;k++)
 85                         ///f[i][k](int memset)相比a[j](ll memset)小很多,减很多次,仍不会到达下界
 86                         a[c][j+k]=max(a[c][j+k],a[c-1][j]+f[i][k]); ///可以使用滚动数组
 87 
 88                 if (vis)
 89                     for (j=0;j<=sum;j++)
 90                         a[c][j+2*i+1]=max(a[c][j+2*i+1],a[c-1][j]+fv[i]);
 91 
 92                 sum+=maxw; ///当然也可以求出tot后再求
 93                 vis=1;
 94                 i=0;
 95                 continue;
 96             }
 97             else
 98                 i++;
 99         }
100         printf("%lld\n",a[c][tot+2]);  ///第一个加号是没有的
101     }
102     return 0;
103 }
104 /*
105 10
106 11
107 100000000+9
108 13
109 111-111111-11
110 20
111 100000000-99999999+1
112 36
113 10000000+12345+0+1+2+3+4+5+6+7+8+9
114 
115 */

 

 

I. Max answer

单调栈+线段树

单调栈
找到一个数左边/右边的第一个大于其的数
把数列出来,容易找到方法
7 8 9 5(则9 8 7 出栈并赋值)


线段树
[l,r]区间 数为d 包含d的最大区间
sum[query_max(d,r)] - sum[query_min(l,d-1)]

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <set>
  7 #include <map>
  8 #include <list>
  9 #include <queue>
 10 #include <vector>
 11 #include <bitset>
 12 #include <algorithm>
 13 #include <iostream>
 14 using namespace std;
 15 #define ll long long
 16 
 17 const double eps=1e-8;
 18 const int maxn=5e5+10;
 19 const ll inf=1e18;
 20 
 21 
 22 int a[maxn],lef[maxn],rig[maxn],st[maxn],maxnum[maxn<<2],minnum[maxn<<2];
 23 ll sum[maxn];
 24 
 25 void build(int ind,int l,int r)
 26 {
 27     if (l==r)
 28         maxnum[ind]=minnum[ind]=l;
 29     else
 30     {
 31         int m=(l+r)>>1;
 32         build(ind<<1,l,m);
 33         build(ind<<1|1,m+1,r);
 34         if (sum[ maxnum[ind<<1] ] > sum[ maxnum[ind<<1|1] ])
 35             maxnum[ind]=maxnum[ind<<1];
 36         else
 37             maxnum[ind]=maxnum[ind<<1|1];
 38 
 39         if (sum[ minnum[ind<<1] ] < sum[ minnum[ind<<1|1] ])
 40             minnum[ind]=minnum[ind<<1];
 41         else
 42             minnum[ind]=minnum[ind<<1|1];
 43     }
 44 }
 45 
 46 int query_max(int ind,int l,int r,int x,int y)
 47 {
 48     if (x>y)
 49         return 0;
 50     if (x<=l && r<=y)
 51         return maxnum[ind];
 52     int m=(l+r)>>1,b=-1;
 53     if (x<=m)
 54         b=query_max(ind<<1,l,m,x,y);
 55     if (m<y)
 56     {
 57         if (b==-1)
 58             return query_max(ind<<1|1,m+1,r,x,y);
 59         else
 60         {
 61             int c=query_max(ind<<1|1,m+1,r,x,y);
 62             if (sum[b]>sum[c])
 63                 return b;
 64             return c;
 65         }
 66     }
 67     return b;   ///
 68 }
 69 
 70 int query_min(int ind,int l,int r,int x,int y)
 71 {
 72     if (x>y)
 73         return 0;
 74     if (x<=l && r<=y)
 75         return minnum[ind];
 76     int m=(l+r)>>1,b=-1;
 77     if (x<=m)
 78         b=query_min(ind<<1,l,m,x,y);
 79     if (m<y)
 80     {
 81         if (b==-1)
 82             return query_min(ind<<1|1,m+1,r,x,y);
 83         else
 84         {
 85             int c=query_min(ind<<1|1,m+1,r,x,y);
 86             if (sum[b]<sum[c])
 87                 return b;
 88             return c;
 89         }
 90     }
 91     return b;   ///
 92 }
 93 
 94 int main()
 95 {
 96     int n,i,g;
 97     ll r;
 98     scanf("%d",&n);
 99     for (i=1;i<=n;i++)
100         scanf("%d",&a[i]);
101 
102     g=0;
103     for (i=1;i<=n;i++)
104     {
105         while (g>0 && a[st[g]]>a[i])
106         {
107             rig[st[g]]=i;
108             g--;
109         }
110         st[++g]=i;
111         sum[i]=sum[i-1]+a[i];
112     }
113 
114     g=0;
115     for (i=n;i>=1;i--)
116     {
117         while (g>0 && a[st[g]]>a[i])
118         {
119             lef[st[g]]=i;
120             g--;
121         }
122         st[++g]=i;
123     }
124 
125     build(1,1,n);
126     r=-inf;
127     for (i=1;i<=n;i++)
128     {
129         if (rig[i]==0)
130             rig[i]=n+1;
131         if (a[i]>=0)
132             r=max(r,a[i]*(sum[rig[i]-1]-sum[lef[i]]));
133         else
134             r=max(r,a[i]*(sum[query_min(1,1,n,i,rig[i]-1)]-max(0ll,sum[query_max(1,1,n,lef[i]+1,i-1)])));///<
135     }
136     printf("%lld",r);
137     return 0;
138 }
139 /*
140 5
141 -2 1 -3 -4 3
142 
143 6
144 -1 -2 -3 -4 -5 -6
145 
146 3
147 -1 -3 -2
148 
149 
150 1
151 -3
152 */

 

J. Distance on the tree

1.树剖

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 #define ll long long
 10 const double eps=1e-8;
 11 const int maxn=1e5+10;
 12 
 13 ///°´ÕձߵĴóСÅÅÐò
 14 ///树剖: 边 而不是 点
 15 
 16 struct node
 17 {
 18     int d;
 19     node *to;
 20 }*e[maxn];
 21 
 22 struct rec
 23 {
 24     int u,v,w,num,mode;
 25     bool operator<(const rec &y) const
 26     {
 27         if (w==y.w)
 28             return mode<y.mode;
 29         return w<y.w;
 30     }
 31 }b[maxn+maxn];
 32 
 33 int sum[maxn];
 34 
 35 int fa[maxn],dep[maxn],siz[maxn],son[maxn];
 36 int id[maxn],top[maxn];
 37 int n,num;
 38 bool vis[maxn];
 39 int tr[maxn<<2];
 40 
 41 void dfs1(int d)
 42 {
 43     int dd;
 44     node* p=e[d];
 45     vis[d]=1;
 46     siz[d]=1;
 47     while (p)
 48     {
 49         dd=p->d;
 50         if (!vis[dd])
 51         {
 52             fa[dd]=d;
 53             dep[dd]=dep[d]+1;
 54             dfs1(dd);
 55             siz[d]+=siz[dd];
 56             if (siz[dd]>siz[son[d]])
 57                 son[d]=dd;
 58         }
 59         p=p->to;
 60     }
 61 }
 62 
 63 void dfs2(int d,int topd)
 64 {
 65     id[d]=++num;
 66     top[d]=topd;
 67     if (son[d]!=0)
 68     {
 69         int dd;
 70         node *p;
 71         dfs2(son[d],topd);
 72 
 73         p=e[d];
 74         while (p)
 75         {
 76             dd=p->d;
 77             if (dd!=son[d] && dd!=fa[d])
 78                 dfs2(dd,dd);
 79             p=p->to;
 80         }
 81     }
 82 }
 83 
 84 void update(int ind,int l,int r,int x)
 85 {
 86     tr[ind]++;
 87     if (l==r)
 88         return;
 89     int m=(l+r)>>1;
 90     if (x<=m)
 91         update(ind<<1,l,m,x);
 92     else
 93         update(ind<<1|1,m+1,r,x);
 94 }
 95 
 96 int query(int ind,int l,int r,int x,int y)
 97 {
 98     if (x<=l && r<=y)
 99         return tr[ind];
100     int m=(l+r)>>1,sum=0;
101     if (x<=m)
102         sum+=query(ind<<1,l,m,x,y);
103     if (m<y)
104         sum+=query(ind<<1|1,m+1,r,x,y);
105     return sum;
106 }
107 
108 int cal(int x,int y)
109 {
110     int sum=0;
111     while (top[x]!=top[y])
112     {
113         if (dep[top[x]]<dep[top[y]])
114             swap(x,y);
115         sum+=query(1,1,n,id[top[x]],id[x]);
116         x=fa[top[x]];
117     }
118 
119     if (dep[x]<dep[y])
120         swap(x,y);
121     ///u,v not the same
122     ///减去根节点
123     return sum+query(1,1,n,id[y]+1,id[x]);
124 }
125 
126 int main()
127 {
128     node *p;
129     int m,i,u,v;
130     scanf("%d%d",&n,&m);
131     for (i=1;i<n;i++)
132     {
133         scanf("%d%d%d",&b[i].u,&b[i].v,&b[i].w);
134         b[i].num=i;
135         b[i].mode=0;
136 
137         p=new node();
138         p->d=b[i].v;
139         p->to=e[b[i].u];
140         e[b[i].u]=p;
141 
142         p=new node();
143         p->d=b[i].u;
144         p->to=e[b[i].v];
145         e[b[i].v]=p;
146     }
147     for (i=n;i<n+m;i++)
148     {
149         scanf("%d%d%d",&b[i].u,&b[i].v,&b[i].w);
150         b[i].num=i;
151         b[i].mode=1;
152     }
153     sort(b+1,b+n+m);
154 
155     fa[1]=1;
156     dfs1(1);
157 
158     dfs2(1,1);
159 
160     for (i=1;i<n+m;i++)
161     {
162         u=b[i].u;
163         v=b[i].v;
164         if (dep[u]<dep[v])
165             swap(u,v);
166 
167         ///往距离远的点加值
168         if (b[i].num<n)
169             update(1,1,n,id[u]);
170         else
171             sum[b[i].num-n+1]=cal(u,v);
172     }
173 
174     for (i=1;i<=m;i++)
175         printf("%d\n",sum[i]);
176     return 0;
177 }

 

2.主席树

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <cstring>
  5 #include <string>
  6 #include <algorithm>
  7 #include <iostream>
  8 using namespace std;
  9 
 10 #define ll long long
 11 const double eps=1e-8;
 12 const int maxn=1e5+10;
 13 const int maxv=1e9;
 14 
 15 ///1-i中的所有数 1-fa(j) -> 1-j 链 主席树
 16 
 17 struct node
 18 {
 19     int d,len,num;
 20     node *to;
 21     node *opp;
 22     int c;
 23 }*e[maxn],*point[maxn];
 24 
 25 struct rec
 26 {///any d,dd 经历两次 可以选择d中加入编号比其大的
 27     int l,r,sum;
 28 }tr[maxn*50];
 29 
 30 int sum[maxn],fa[maxn],be[maxn],num;
 31 bool vis[maxn];
 32 
 33 void build(int ind_old,int ind,int l,int r,int x)
 34 {
 35     if (l==r)   ///single
 36     {
 37         tr[ind].sum=tr[ind_old].sum+1;
 38         return;
 39     }
 40     int m=(l+r)>>1;
 41     if (x<=m)
 42     {
 43         tr[ind].r=tr[ind_old].r;
 44         tr[ind].l=++num;
 45         build(tr[ind_old].l,tr[ind].l,l,m,x);
 46     }
 47     else
 48     {
 49         tr[ind].l=tr[ind_old].l;
 50         tr[ind].r=++num;
 51         build(tr[ind_old].r,tr[ind].r,m+1,r,x);
 52     }
 53     tr[ind].sum=tr[tr[ind].l].sum + tr[tr[ind].r].sum;
 54 }
 55 
 56 int query(int ind,int l,int r,int k)    ///[1,k]
 57 {
 58     if (r<=k)
 59         return tr[ind].sum;
 60     int m=(l+r)>>1,sum=0;
 61     if (tr[ind].l!=0)  ///存在(该点在线段树中被创建)
 62         sum+=query(tr[ind].l,l,m,k);
 63     if (m<k && tr[ind].r!=0)
 64         sum+=query(tr[ind].r,m+1,r,k);
 65     return sum;
 66 }
 67 
 68 void dfs(int d)
 69 {
 70     node *p=e[d];
 71     int dd;
 72     vis[d]=1;
 73     while (p)
 74     {
 75         dd=p->d;
 76         if (!vis[dd])
 77         {
 78             be[dd]=++num;
 79             build(be[d],be[dd],1,maxv,p->len);
 80             dfs(dd);
 81         }
 82         p=p->to;
 83     }
 84 }
 85 
 86 int getf(int d)
 87 {
 88     if (fa[d]==d)
 89         return d;
 90     fa[d]=getf(fa[d]);
 91     return fa[d];
 92 }
 93 
 94 void lca(int d)
 95 {
 96     int dd,x,y;
 97     node *p=e[d];
 98     vis[d]=1;
 99     while (p)
100     {
101         dd=p->d;
102         if (!vis[dd])
103         {
104             lca(dd);
105             x=getf(d);
106             y=getf(dd);
107             fa[y]=x;
108         }
109         p=p->to;
110     }
111 
112     p=point[d];
113     while (p)
114     {
115         dd=p->d;
116         ///也许出现一次,也许出现两次
117         if (vis[dd] && p->opp->c==0)
118         {
119             sum[p->num]-=query(be[getf(dd)],1,maxv,p->len)*2;
120             p->c=1;
121         }
122 
123         p=p->to;
124     }
125 }
126 
127 int main()
128 {
129     node *p,*pp;
130     int n,m,u,v,w,k,i;
131     scanf("%d%d",&n,&m);
132     for (i=1;i<=n;i++)
133         fa[i]=i;
134 
135     for (i=1;i<n;i++)
136     {
137         scanf("%d%d%d",&u,&v,&w);
138 
139         p=new node();
140         p->d=v;
141         p->len=w;
142         p->to=e[u];
143         e[u]=p;
144 
145         p=new node();
146         p->d=u;
147         p->len=w;
148         p->to=e[v];
149         e[v]=p;
150     }
151 
152     num=1;
153     be[1]=1;
154 
155     dfs(1);
156 
157     for (i=1;i<=m;i++)
158     {
159         scanf("%d%d%d",&u,&v,&k);
160 
161         p=new node();
162         pp=new node();
163 
164         p->d=v;
165         p->len=k;
166         p->num=i;
167         p->to=point[u];
168         p->opp=pp;
169         p->c=0;
170         point[u]=p;
171 
172         pp->d=u;
173         pp->len=k;
174         pp->num=i;
175         pp->to=point[v];
176         pp->opp=p;
177         pp->c=0;
178         point[v]=pp;
179 
180         sum[i]=query(be[u],1,maxv,k) + query(be[v],1,maxv,k);
181 
182 //        printf("%d %d\n",query(be[u],1,maxv,k),query(be[v],1,maxv,k));
183     }
184 
185     memset(vis,0,sizeof(vis));
186     lca(1);
187 
188     for (i=1;i<=m;i++)
189         printf("%d\n",sum[i]);
190     return 0;
191 }

 

posted @ 2019-04-21 01:00  congmingyige  阅读(206)  评论(0编辑  收藏  举报