• 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
    28
    496
    8128
    33550336");
    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
    ",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
    ",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
    ",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
    ",f[x][t]^f[x][s-1]);
                }
                else
                    printf("0
    ");
            }
        }
        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?'
    ':' ');
    62             printf("%d%c",f[y][1][i].a[j] &1,j==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
    ");
    49         else
    50             printf("NO
    ");
    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
    ",'+');///43
     41 //    printf("%d
    ",'-');///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
    ",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
    ",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
    ",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
    ",sum[i]);
    190     return 0;
    191 }
  • 相关阅读:
    Arduino语法-变量和常量
    Arduino-函数库和程序架构介绍
    第十章浮力题汇总
    pyqt5-按钮基类-QAbstractButton
    在Windows上安装Arduino-IDE
    Arduino-接口图
    python-文件及文件夹操作
    Qt WebRTC demo
    多线程使用信号量sem_init,sem_wait,sem_post
    华为公司内部培训资料_介绍RTSP的消息、信令等
  • 原文地址:https://www.cnblogs.com/cmyg/p/10743597.html
Copyright © 2020-2023  润新知