NOIP2020 review

Common Templates for League Difficulty

Basic skills:

Header files and input and output:

#include<cstdio> //Input and output header files

#include<cstring> //String header file, array overall assignment header file

#include<cstdlib> //random number header file

#include<algorithm>//Quick row header file

#include<cmath> //sqrt and other mathematical function header files (abs and the like are recommended to be typed by hand, because the built-in ones may be out of the pot)

#include<ctime> //random number initialization header file

using namespace std;//Things to be typed when algorithm/other header files that do not start with c

char str[10];

int main()

{

       int a,b;

       scanf("%d%d",&a,&b);

       printf("%d %d %d\n",a,b,a+b);

long long c,d;

       scanf("%lld%lld",&c,&d);

       printf("%lld %lld %lld\n",c,d,c+d);

       scanf("\n%s",str+1); //Note that +1 means starting from the first position (if you do not write +1, it will start from the zeroth position by default)

       int len=strlen(str+1); //There is +1 in front, and +1 is also required when finding the length

       for (int i=1;i<=len;i++) printf("%c",str[i]); //The output of the string is recommended to output character by character

       printf("\n");

       double x,y;

       scanf("%lf%lf",&x,&y);

       printf("%.6lf\n",x+y); //Pay attention to how to keep decimals

}

The overall assignment and clearing of the array:

#include<cstdio>

#include<cstring>//Remember to open this library (you may not report an error if you don’t open the machine, but it will hang when you submit it)

int a[10010],b[10010];

int main()

{

       memset(a,0,sizeof(a)); //a overall assignment value is 0

       memset(a,100,sizeof(a));//a overall assignment is a larger value

       memcpy(a,b,sizeof(b));//The overall assignment of a is the value corresponding to each bit of the b array

       return 0;

}

Edge storage method:

#include<cstdio>

int all;

int las[5010],nxt[10010],to[10010]; //Pay attention to the double space of nxt and to (for two-way sides), and note that the variable name should not be spelled in English (it is easy to get out of the pot in different compilation environments). Las[x] indicates the last occurrence of the point numbered x. Nxt[tot] indicates the previous position to which the point corresponding to the current position tot jumps to, and to[tot] indicates the point to which the point corresponding to the current position tot is connected to. To find all the points connected to x is to jump forward from las[x].

void insert(int x,int y)

{

       nxt[++tot]=las[x];

       las[x]=all;

       to[tot]=y;

}

int main()

{

       int m;

       scanf("%d",&m);

       int x,y;

       for (int i=1;i<=m;i++)

       {

              scanf("%d%d",&x,&y);

              insert(x,y); insert(y,x); //two-way edge

       }

x=1;

       for (int i=las[x];i;i=nxt[i]) //enumerate all points connected to x and output

       {

              printf("%d\n",to[i]);

       }

}

Quick row:

#include<cstdio>

#include<algorithm>//header file

using namespace std;//Remember to add

int a[1010];

bool cmp(int x,int y)

{

       return x>y; //If the symbol is less than, it is sorted from small to large, and if the symbol is greater than, it is sorted from large to small.

}

int main()

{

       int n;

       scanf("%d",&n);

       for (int i=1;i<=n;i++) scanf("%d",&a[i]);

       sort(a+1,a+1+n,cmp);//If you don't write cmp, it will default from small to large

       for (int i=1;i<=n;i++) printf("%d ",a[i]);

       return 0;

}

Structural multi-keyword quick sorting:

#include<cstdio>

#include<algorithm>

using namespace std;

struct grand{

       int x,num;     

} a[1010];

bool cmp(grand a, grand b)

{

       return (ax<bx) || (ax==bx && a.num<b.num); .x is the first keyword, .num is the second keyword, from small to large

}

int main()

{

       int n;

       scanf("%d",&n);

       for (int i=1;i<=n;i++) scanf("%d",&a[i].x),a[i].num=i;

       sort(a+1,a+1+n,cmp);

       for (int i=1;i<=n;i++) printf("%d ",a[i].x);

       return 0;

}

EOF:

When the topic says to enter several sets of data, it ends with the end of file.

#include<cstdio>

int main()

{

       int n,x;

       while (scanf("%d",&n)!=EOF)

       {

              scanf("%d",&x);

              printf("%d %d\n",n,x);

       }

       return 0;

}

Moisture/watching/finding rules:

  1. Pseudo-greedy can sometimes be a lot of water
  2. If you don't know how to solve math problems, just play the table to find the rules
  3. If the data range is small, you can create a table to build a database

Random number: //It can be used when creating data or playing metaphysics, and it is not required to master

#include<cstdio>

#include<cstdlib>//exclusive header file

#include<ctime>//exclusive header file

int main()

{

       srand(time(0)); //Random seed initialization

       int x=rand()%10+1; //The range of rand should be more than 30,000 in this machine

       printf("%d\n",x);

       return 0;

}

Graph Theory:

Shortest path (spfa):

var     a:array[1..1000,0..1000]of longint;

        f:array[1..1000,1..1000]of longint;

        dis:array[1..1000]of longint;

        data:array[1..100000]of longint;

        bz:array[1..1000]of boolean;

        x,y,t,n,m,i,j,l,r:longint;

begin

        readln(n,m);

        fillchar(f,sizeof(f),10);

        for i:=1 to m do

        begin

                readln(x,y,t);

                if f[x,y]<168430090 then

                begin

                        if f[x,y]>t then f[x,y]:=t;

                than otherwise

                begin

                        inc(a[x,0]);

                        a[x,a[x,0]]:=y;

                        f[x,y]:=t;

                end;

        end;

        fillchar(data,sizeof(data),0);

        fillchar(dis,sizeof(dis),10);

        fillchar(bz,sizeof(bz),false);

        i:=1;

        l:=0;

        r:=1;

        data[1]:=i;

        dis[i]:=0;

        while l<r do

        begin

                inc(l);

                t:=data[l];

                for j:=1 to a[t,0] do

                        if dis[t]+f[t,a[t,j]]<dis[a[t,j]] then

                        begin

                                dis[a[t,j]]:=dis[t]+f[t,a[t,j]];

                                if bz[a[t,j]]=false then

                                begin

                                        bz[a[t,j]]:=true;

                                        inc(r);

                                        data[r]:=a[t,j];

                                end;

                        end;

                bz[t]:=false;

        end;

        for j:=1 to n do

                if dis[j]<f[i,j] then f[i,j]:=dis[j];

        for i:=2 to n do writeln(f[1,i]); //This is the shortest path from choosing 1 as the starting point to all other points

end.

 

Minimum spanning tree:

#include<cstdio>

#include<algorithm>

using namespace std;

struct zzx{

       int x,y,z;

} a[10010];

int fa[10010];

bool cmp(zzx a,zzx b)

{

       return a.z<b.z;      

}

int father(int x)

{

       if (x==fa[x]) return x;

       fa[x]=father(fa[x]);

}

int main()

{

       int n,m;

       scanf("%d%d",&n,&m);

       for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);

       sort(a+1,a+1+m,cmp);

       for (int i=1;i<=n;i++) fa[i]=i;

       int s=0;

       for (int i=1;i<=m;i++)

       {

              int fax=father(a[i].x);

              int fay=father(a[i].y);

              if (fax!=fay)

              {

                     s=s+a[i].z;

                     fa[fax]=fay;

              }

       }

       printf("%d\n",s);

}

 

LCA:

//fa represents the parent node of each point, deep represents the depth of each point

int fa[100],deep[100];

int LCA(int a,int b)

{

       //In the function, ensure that the depth of a is greater than the depth of b, which is convenient for later operations.

       if(deep[a]<deep[b])

              swap(a,b);

       //Let b continuously jump to his parent node until the same depth as a

       while(deep[a]>deep[b])

              b=deep[b];

       //Let a and b jump up at the same time until they meet.

       while(a!=b)

       {

              a=deep[a];

              b=deep[b];

       }

       return a;

}

Doubling:

https://blog.csdn.net/Q_M_X_D_D_/article/details/89924963 (with explanation)

//fa represents the parent node of each point

int fa[100],DP[100][20];

void init()

{

       //n is the number of nodes, first initialize the DP array

       for(int i=1;i<=n;i++)

              dp[i][0]=fa[i];

       //Dynamic programming to find the entire DP array

       for(int j=1;(1<<j)<=n;j++)

              for(int i=1;i<=n;i++)

                     DP[i][j]=DP[DP[i][j-1]][j-1];

}

//query function

int LCA(int a,int b)

{

    //Ensure that the depth of a is greater than b, which is convenient for later operations.

       if(dep[a]<dep[b])

              swap(a,b);

    //Let a continue to jump up until it is at the same depth as b

    //If it cannot be ensured that the depth of a is greater than b, it is impossible to determine whether a or b is jumping up in this step

       for(int i=19;i>=0;i--)

       {

        // Jumping up is the process of depth reduction

              if(dep[a]-(1<<i)>=dep[b])

                     a=dp[a][i];

       }

    //If the two are at the same depth and meet exactly, then this point is LCA

       if(a==b)

              return a;

    //a and b jump up at the same time, traverse the step size from large to small, jump up when it meets a suitable one, and reduce the step size if it is not suitable

       for(int i=19;i>=0;i--)

       {

        //If the two do not meet, jump up

              if(dp[a][i]!=dp[b][i])

              {

                     a=dp[a][i];

                     b=dp[b][i];

              }

       }

    //Finally, a and b jumped to the next layer of LCA, and LCA is the parent node of a and b

       return dp[a][0];

}

 

difference:

Ordinal difference: https://gmoj.net/junior/#main/show/2162

For a rectangle, through the addition and subtraction of the values ​​​​of the four vertex positions, the addition and subtraction operations of all positions in the rectangle are realized. Use the prefix and .

var     n,q,x,y,i,j,x1,y1,x2,y2:longint;

        a:array[1..3001,1..3001]of longint;

        sum:array[0..3000,0..3000]of longint;

begin

        assign(input,'square.in');reset(input);

        assign(output,'square.out');rewrite(output);

        readln(n);

        for i:=1 to n do

        begin

                readln(x1,y1,x2,y2);

                inc(a[x1,y1]);

                dec(a[x1,y2+1]);

                dec(a[x2+1,y1]);

                inc(a[x2+1,y2+1]);

        end;

        for i:=1 to 3000 do

                for j:=1 to 3000 do

                        sum[i,j]:=sum[i-1,j]+sum[i,j-1]-sum[i-1,j-1]+a[i,j] ;

        readln(q);

        for i:=1 to q do

        begin

                readln(x,y);

                writeln(sum[x,y]);

        end;

        close(input);close(output);

end.

Tree difference:

Two points x and y on the tree make all edges + a on the path from x to y. Then put the parent side of x + a, the parent side of y + a, and the parent side of their lca -2a. Query the value of an edge by querying the sum of the subtrees of the edge.

 

Two points x, y on the tree make all points + a on the path from x to y. Then put the value of x + a, the value of y + a, the value of their lca - a, and the value of their lca's father - a. Query the value of a point by querying its subtree sum.

 

 

Bipartite graph matching (Hungarian algorithm):

https://blog.csdn.net/sunny_hun/article/details/80627351 (with explanation)

#include<cstdio>

#include<cstring>

int a[1010][1010];

int f[1010];

bool bz[1010];

bool pd(int x)

{

       for (int i=1;i<=a[x][0];i++)

              if (!bz[a[x][i]])

              {

                     bz[a[x][i]]=true;

                     if (f[a[x][i]]==0 || pd(f[a[x][i]]))     

                     {

                            f[a[x][i]]=x;

                            return true;

                     }

              }

       return false;

}

int main()

{

       int n,m,e;

       scanf("%d%d%d",&n,&m,&e);

       int x,y;

       for (int i=1;i<=e;i++)

       {

              scanf("%d%d",&x,&y);

              if (y>m) continue;

              a[x][++a[x][0]]=y;

       }

       int ans=0;

       for (int i=1;i<=n;i++)

       {

              memset(bz,0,sizeof(bz));

              if (pd(i)) ans++;

       }

       printf("%d\n",ans);

       return 0;

}

 

Common expectation calculations:

Three points, two adjacent points are connected by bidirectional edges.

 

Let f[i] represent the expected number of steps from point 1 to point i for the first time.

Then f[1]=0, f[2]=1. Now find f[3].

Consider only going from point 1 to point 2 at the beginning. At point 2, you can go back to point 1 or go to point 3, each with a probability of 1/2. If it goes to number 3, it ends. If you go back to No. 1, it is equivalent to starting from the beginning.

Using equation thinking:

f[3]=1/2*(f[2]+1)+1/2*(f[2]+1+f[3]), the first half is to go to point 3, and the second half is to return to point 1 and start again. The solution is f[3]=4.

The expectation calculation on the tree can also use a similar equation idea.

 

Tree chain split:

https://blog.csdn.net/HiChocolate/article/details/77170675 (template, handling)

Divide tree edges into light and heavy edges. Each level of the tree has one and only one multiple edge, which is the edge that has the most descendants (the largest subtree size) for the connected son. The son connected to Chongbian is called Chongzi.

The process of splitting the tree chain is 2 dfs

The first time: according to the definition to find out the heavy edge, heavy son

The second time: According to the principle of prioritizing heavy edges, a dfs sequence is created. The position of point x in the dfs sequence is recorded as tree[x], and the starting point top[x] of the heavy chain to which each point belongs is calculated.

After splitting, each heavy chain is equivalent to a section, which is maintained by a data structure (such as a line segment tree, etc.).

Connect all the heavy chains end to end, put them on the same data structure, and then maintain this whole.

If u and v are on the same heavy chain, directly use the data structure to modify the value between tree[u] and tree[v] or query the answer.

If u and v are not on the same heavy chain, while modifying, put u and v on the same heavy chain, and then it becomes the above situation.

Specific operation: we jump the party x with greater depth to his fa[top[x]], and modify or query tree[top[x]]~tree[x]

Since a heavy chain is a continuous interval in the data structure, it is no problem to directly query tree[top[x]]~tree[x].

Number Theory:

Gcd:

#include<cstdio>

int gcd(int x,int y)

{

       if (x%y==0) return y; else return gcd(y,x%y);

}

int main()

{

       int a,b;

       scanf("%d%d",&a,&b);

       printf("%d\n",gcd(a,b));

       return 0;

}

Quick power:

#include<cstdio>

long long mi(long long a,long long b)

{

       long long s=1;

       while (b)

       {

              if (b&1) s=s*a;

              a=a*a;

              b/=2;

       }

       return s;

}

int main()

{

       int n,m;

       scanf("%d%d",&n,&m);

       long long s=mi(n,m);

       printf("%lld\n",s);

       return 0;

}

Find the inverse of a number in the sense of %p:

When p is a prime number, dividing a number by x is equivalent to multiplying by x^(p-2). In this way, the division operation in the modular sense is realized.

When p is not a prime number, there is no inverse element, and division operations should be avoided at this time.

 

Prime number sieve:

#include<cstdio>

bool bz[100010];

int zhi[100010];

int main()

{

       int n;

       scanf("%d",&n);

       for (int i=3;i*i<=n;i+=2)

              if (!bz[i])

                     for (int j=i;i*j<=n;j+=2) bz[i*j]=true; //Note that bz does not mark even numbers

       zhi[0]=1; zhi[1]=2;

       for (int i=3;i<=n;i+=2)

              if (!bz[i]) zhi[++zhi[0]]=i;

       for (int i=1;i<=zhi[0];i++) printf("%d ",zhi[i]);

       return 0;

}

 

Excd:

https://www.cnblogs.com/mrclr/p/9380300.html

exgcd can be used to solve the equation ax +by = gcd(a, b) for a set of x,y.

int exgcd(int a,int b,int &x,int &y) //注意x,y前的&

{

       int s;

       if (!b)

       {

              s=a,x=1,y=0;

              return s;

       }

       s=exgcd(b,a%b,y,x); y-=a/b*x;

       return s;

}

 

Turtle ride:

We have two numbers a, b, and require the result of a*b%p.

What if a and b do not exceed long long, but if they are multiplied together, they exceed?

Turn a*b into b and add a, and then like a fast power, only each multiplication becomes an addition.

In this way, since it is added bit by bit, the modulo is taken every time it is added, so it will not explode long long

https://blog.csdn.net/jz_terry/article/details/86670193

long long cheng(long long a,long long b)

{

       long long s=0;

       while (b)

       {

              if (b&1) s=(s+a)%Mo;

              a=(a+a)%I;

              b>>=1;

       }

       return s;

}

 

Linearly find the inverse of 1~n in the sense of %p: recursion, f[i]=f[p%i]*(pp/i)%p  

Derivation: let p=a*i+b, then a*i+b 0 (%p). Because the inverse of i is required, the formula should be transformed into the form of i^-1=.... That is, 1/i=-a/b=-y/x*(y%x)^-1, in order to avoid negative numbers, p should also be added. So get the above recursive formula.

 

Linearly calculate the factorial i of each number i in 1~n! The inverse of: f[i]=f[i+1]*(i+1)%p.

Proof: i!^-1=(i+1)!^-1)(i+1) (multiplying (i+1) is to eliminate (i+1)^-1, so that it can be pushed backwards from n)

DP

Knapsack problem dp:

01 backpack:

There are t items and a knapsack with capacity n. There is only one i-th item, the volume is v[i], and the value is w[i]. Select items to be loaded into the backpack so that the sum of the volumes of these items does not exceed the capacity of the backpack, and the sum of the values ​​is the largest, and find the maximum value.

var     i,j,t,n:longint;

        f:array[0..1000,0..1000]of longint;

        w,v:array[1..1000]of longint;

function max(a,b:longint):longint;

begin

        if a>b then exit(a) else exit(b);

end;

begin

        readln(n,t); //t is the number of items, n is the number of capacity

        for i:=1 to t do

                readln(w[i],v[i]);

        for i:=1 to t do

                for j:=1 to n do

                        if j>=w[i] then

                        f[i,j]:=max(f[i-1,j],f[i-1,j-w[i]]+v[i]) else

                        f[i,j]:=f[i-1,j];

        writeln(f[t,n]);

end.

Complete Backpack:

There are t items and a knapsack with capacity n. There are infinite number of i-th items, the volume is v[i], and the value is w[i].
Select items to be loaded into the backpack so that the sum of the volumes of these items does not exceed the capacity of the backpack, and the sum of the values ​​is the largest, and find the maximum value.

var     w,v:array[0..10000]of longint;

        f:array[0..1000,0..10000]of longint;

        i,j,n,m,k,l,t:longint;

function max(x,y:longint):longint;

begin

        if x>y then exit(x) else exit(y);

end;

begin

        readln(n,t);

        for i:=1 to t do readln(w[i],v[i]);

        for i:=1 to t do

        begin

                for j:=1 to n do

                begin

                         for k:=0 to j div w[i] do

                         begin

                                if w[i]*k>j then f[i,j]:=f[i-1,j]

                                else f[i,j]:=max(f[i,j],f[i-1,j-w[i]*k]+v[i]*k)

                         end;

                end;

        end;

        write(f[t,n]);

end.

 

The dp of the longest non-decreasing subsequence:

Let b[i] represent the minimum energy of the i-th bit of the longest non-decreasing subsequence (to satisfy that the i-th bit is not less than the i-1th bit)

Each time a new number is added, if the subsequence can be increased, it will be increased, and if it cannot be increased, see if b can be updated.

var n,i,j:longint;

        a,b:array[0..100]of longint;

begin

        readln(n);

        for i:=1 to n do read(a[i]);

        b[0]:=0;

        for i:=1 to n do

        begin

                if a[i]>=b[b[0]] then

                begin

                        inc(b[0]);

                        b[b[0]]:=a[i];

                than otherwise

                begin

                        for j:=b[0]-1 downto 1 do //If this part is changed to dichotomy, the complexity is nlogn.

                                if a[i]>=b[j] then

                                begin

                                        b[j+1]:=a[i];

                                        break;

                                end;

                        if b[1]>a[i] then b[1]:=a[i];

                end;

        end;

        writeln(b[0]);

end.

 

Tree dp:

A tree with n points, each point has a weight (positive or negative), find the weight and the largest subtree in the tree, and output the largest weight.

#include<cstdio>

int all;

int nxt[2010],to[2010],las[1010];

int f[1010];

int a[1010];

void insert(int x,int y)

{

       nxt[++tot]=las[x];

       las[x]=all;

       to[tot]=y;

}

void dfs(int x,int fa)

{

       f[x]=a[x];

       for (int i=las[x];i;i=nxt[i])

              if (to[i]!=fa)

              {

                     dfs(to[i],x);

                     f[x]=f[x]+f[to[i]];

              }

}

int main()

{

       int n;

       scanf("%d",&n);

       for (int i=1;i<=n-1;i++)

       {

              int x,y;

              insert(x,y);

              insert(y,x);

       }

       for (int i=1;i<=n;i++) scanf("%d",&a[i]);

       dfs(1,0);

       int mx=0;

       for (int i=1;i<=n;i++)

              if (f[i]>mx) mx=f[i];

       printf("%d\n",mx);

}

 

Monotonic queue:

Constantly read elements into the cache array, remove the oldest element from time to time, and ask the smallest element in the current cache array from time to time.

https://blog.csdn.net/ljd201724114126/article/details/80663855

 

Slope optimization:

https://blog.csdn.net/jz_terry/article/details/103212006

other:

Two points: (Easy to get out of the pot, it is recommended to debug or simulate several times after playing)

A sorted sequence from small to large, find the position of the first number greater than x.

#include<cstdio>

int a[1010];

int main()

{

       int n,x;

       scanf("%d",&n);

       for (int i=1;i<=n;i++) scanf("%d",&a[i]);

       scanf("%d",&x);

       int l=1; int r=n+1; //Because r represents the minimum position that satisfies the condition, the initial value cannot be n (a[n] is not necessarily greater than x)

       while (l<r)

       {

              int mid=(l+r)/2;

              if (a[mid]<=x) l=mid+1; else r=mid;

       }

       printf("%d\n",r);

       return 0;

}

A sorted sequence from small to large, find the position of the last number less than x.

#include<cstdio>

int a[1010];

int main()

{

       int n,x;

       scanf("%d",&n);

       for (int i=1;i<=n;i++) scanf("%d",&a[i]);

       scanf("%d",&x);

       int l=1; int r=n; //definition l-1 is satisfied, r+1 is not satisfied

       while (l<=r) //Different from the previous ones, it also needs to be done when l=r, to judge whether l is full or not

       {

              int mid=(l+r)/2;

              if (a[mid]>=x) r=mid-1; else l=mid+1;

       }

       printf("%d\n",l-1);

       return 0;

}

 

Segment tree:

Single-point modification, interval query:

#include<cstdio>

#include<cstdlib>

#include<iostream>

using namespace std;

int n,m,k,x,y,ans;

int a[100010];

int tree[400010];

void maketree(int x,int st,int en)

{

       int m;

       if (st==en) tree[x]=a[st];

       else

       {

              m=(st+en)>>1;

              maketree(x+x,st,m);

              maketree(x+x+1,m+1,en);

              tree[x]=max(tree[x+x],tree[x+x+1]);

       }

}

void change(int x,int st,int en,int p,int value)

{

       int m;

       if (st==en) tree[x]=value;

       else

       {

              m=(st+en)>>1;

              if (p<=m)

              {

                     change(x+x,st,m,p,value);

              }

              else change(x+x+1,m+1,en,p,value);

              tree[x]=max(tree[x+x],tree[x+x+1]);

       }

}

void find(int x,int st,int en,int l,int r)

{

       int m;

       if (l==st && r==en) ans=max(tree[x],ans);

       else

       {

              m=(st+en)>>1;

              if (r<=m) find(x+x,st,m,l,r);

              else if (l>m) find(x+x+1,m+1,en,l,r);

              else

              {

                     find(x+x,st,m,l,m);

                     find(x+x+1,m+1,en,m+1,r);

              }

       }

}

int main()

{

       scanf("%d",&n);

       for (int i=1;i<=n;i++)

       {

              scanf("%d",&a[i]);

       }

       maketree(1,1,n);

       scanf("%d",&m);

       for (int i=1;i<=m;i++)

       {

              scanf("%d%d%d",&k,&x,&y);

              if (k==1)

              {

                     change(1,1,n,x,y);

              }

              else if (k==2)

              {

                     ans=0;

                     find(1,1,n,x,y);

                     printf("%d\n",ans);

              }

       }

}

Interval modification, interval query:

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<iostream>

using namespace std;

long long f[300010];

int a[300010];

int g[300010];

long long ans;

int n,m;

int x,l,r,c;

void maketree(int x,int st,int en)

{

       int mid;

       if (st==en) f[x]=a[st];

       else

       {

              mid=(st+one)/2;

              maketree(x*2,st,mid);

              maketree(x*2+1,mid+1,en);

              f[x]=max(f[x*2],f[x*2+1]);     

       }

}

void update(int x,int st,int en,int l,int r,int v)

{

       int mid;

       if (st==l && en==r)

       {

              f[x]=f[x]+v;

              g[x]=g[x]+v;

       }

       else

       {

              f[x*2]+=g[x];

              f[x*2+1]+=g[x];

              g[x*2]+=g[x];

              g[x*2+1]+=g[x];

              g[x]=0;

              mid=(st+one)/2;

              if (r<=mid) update(x*2,st,mid,l,r,v);

              else if (l>mid) update(x*2+1,mid+1,en,l,r,v);

              else

              {

                     update(x*2,st,mid,l,mid,v);

                     update(x*2+1,mid+1,en,mid+1,r,v);

              }

              f[x]=max(f[x*2],f[x*2+1]);

       }

}

void getmax(int x,int st,int en,int l,int r)

{

       int mid;

       if (st==l && en==r)

       {

              ans=max(ans,f[x]);

       }

       else

       {

              //

              f[x*2]+=g[x];

              f[x*2+1]+=g[x];

              g[x*2]+=g[x];

              g[x*2+1]+=g[x];

              g[x]=0;

              //

              mid=(st+one)/2;

              if (r<=mid) getmax(x*2,st,mid,l,r);

              else if (l>mid) getmax(x*2+1,mid+1,en,l,r);

              else

              {

                     getmax(x*2,st,mid,l,mid);

                     getmax(x*2+1,mid+1,en,mid+1,r);

              }

       }

}

int main()

{

       scanf("%d",&n);

       for (int i=1;i<=n;i++)

       {

              scanf("%d",&a[i]);

       }

       maketree(1,1,n);

       scanf("%d",&m);

       for (int i=1;i<=m;i++)

       {

              scanf("%d",&x);

              if (x==1)

              {

                     scanf("%d%d%d",&l,&r,&c);

                     update(1,1,n,l,r,c);

              }

              else

              {

                     ans=-2147483647000;

                     scanf("%d%d",&l,&r);

                     getmax(1,1,n,l,r);

                     printf("%d\n",ans);

              }

       }

       //system("pause");

       return 0;

}

Tree array:

https://blog.csdn.net/jz_terry/article/details/78543825

记得two[i]=i&(-i);

Single point modification, interval query

#include<cstdio>

int a[100001];

int two[100001];

int c[100001];

int sum[100001];

char ch;

int qiuhe(int x)

{

       int s=0;

       while (x>0)

       {

              s+=c[x];

              x=x-two[x];

       }

       return s;

}

int main()

{

       int n,m;

       scanf("%d",&n);

       int i;

       for (i=1;i<=n;i++)

       {

              scanf("%d",&a[i]);

              sum[i]=sum[i-1]+a[i];

       }

       for (i=1;i<=n;i++) two[i]=i&(-i);

       for (i=1;i<=n;i++)

              c[i]=sum[i]-sum[i-two[i]];

       scanf("%d",&m);

       int x,y,k,t;

       for (i=1;i<=m;i++)

       {

              scanf("\n%c%d%d",&ch,&x,&y);

              if (ch=='C')

              {

                     k=x;

                     t=a[x];

                     a[x]=y;

                     while (k<=n)

                     {

                            c[k]=c[k]-t+y;

                            k=k+two[k];

                     }

              } else

              {

                     printf("%d\n",qiuhe(y)-qiuhe(x-1));                   

              }

       }

       return 0;

}

KMP:

#include<cstdio>

char a[100001];

char b[100001];

int p[100001];

int f[100001];

int main()

{

       int n,m;

       scanf("%d%d",&n,&m);

       scanf("%s",a+1);

       scanf("%s",b+1);

       int i,j;

       for (i=2;i<=m;i++)

       {

              j=p[i-1]; //p[i] indicates a suffix ending with the i-th digit in the matching string, that is, ip[i]+1~i, which is the same as 1~p[i]. To make p[i] the largest under the above conditions.

              while (j>0 && b[j+1]!=b[i]) j=p[j]; //Continue to use p[i-1] first, and then because it needs to satisfy one more bit, it keeps mismatching and keeps adjusting and reducing.

              if (b[j+1]==b[i]) p[i]=j+1; //Update if found legal, if not found p[i] is 0

       }

       for (i=1;i<=n;i++)

       {

              j=f[i-1];//f[i] means that the i-th bit in the original string is a suffix, if[i]+1~i of the original string is the same as 1~f[i] of the matched string, maximizing f[i].

              while (j>0 && b[j+1]!=a[i]) j=p[j]; First use f[i-1], and then because it needs to satisfy one more bit, it keeps mismatching and keeps adjusting and reducing.

              if (b[j+1]==a[i])

              {

                     f[i]=j+1;

                     if (f[i]==m)

                     {

                            printf("%d\n",i-m+1);

                            f[i]=p[f[i]]; //After finding a complete match, in order to continue to find the next one, f[i] needs to jump back one step.

                     }

              }

       }

       return 0;

}

Minimum heap:

https://blog.csdn.net/hrn1216/article/details/51465270 (if you forget the principle)

heap sort

#include<cstdio>

#include<cstring>

#include<cstdlib>

using namespace std;

int g[300010],i,n,a;

void up(int t)

{

       int q;

       if(t==1)return;

       q=t/2;

       if(g[q]>g[t])

       {

              a=g[q]; g[q]=g[t]; g[t]=a;

              up(q);

       }

}

void down(int t)

{

       int p;

       if(t*2>n)return;

       p=t*2;

       if ((p<n)&&(g[p+1]<g[p]))p++;

       if(g[p]<g[t])

       {

              a=g[p]; g[p]=g[t]; g[t]=a;

              down(p);

       }     

}

int main()

{

       scanf("%d",&n);

       for(i=1;i<=n;i++)

       {

              scanf("%d",&g[i]);

              up(i);

       }

       for(;n>1;)

       {

              printf("%d\n",g[1]);

              g[1]=g[n];

              n--;

              down(1);

       }

       printf("%d\n",g[1]);

}

 

hash:

By multiplying each bit with a different coefficient and taking the modulus, convert a string/a large number into a relatively small number (equivalent to giving it a number), and try to store it in the position of the number in the array. If the subscript of the number in the array has already been stored, and the original string is different, the number will be gradually accumulated until a vacancy is found and inserted.

 

Horse-drawn cart:

https://blog.csdn.net/Gao_Jue_Yi/article/details/81435328 (your previous blog)

#include<cstdio>

#include<cstring>

char a[11000010];

char b[22000010];

int p[22000010];

int main()

{

       scanf("%s",a+1);

       int n=strlen(a+1);

       b[1]='*';

       int m=1;

       for (int i=1;i<=n;i++)

              b[++m]=a[i],b[++m]='*';

       int x=0; int y=0;

       int ans=0;

       for (int i=1;i<=m;i++)

       {

              if (y>i)

              {

                     if (p[x*2-i]+i-1<=y) p[i]=p[x*2-i]; else p[i]=y-i+1;

              } else p[i]=1;

              while (i-p[i]>=1 && i+p[i]<=m && b[i-p[i]]==b[i+p[i]]) p[i]++;

              if (y<i+p[i]-1)

              {

                     y=i+p[i]-1;

                     x=i; 

              }

              if (p[i]-1>ans) ans=p[i]-1;

       }

       printf("%d\n",ans);

       return 0;

}

 

Network stream: ( should not belong to the scope of the league , not required to master)

#include<cstdio>

#include<cstring>

int n,m,S,T;

int las[10010],nxt[200010],to[200010];

long long num[200010];

int gap[10010],dis[10010];

int all=-1;

int min(long long x,long long y)

{

       if (x<y) return x; else return y;

}

void insert(int x,int y,long long z)

{

       nxt[++tot]=las[x];

       las[x]=all;

       to[tot]=y;

       num[all]=z;

}

long long dfs(int x,long long s)

{

       if (x==T) return s; //has already flowed to the sink, return flow

       int have=0; //How much traffic has flowed to sink T

       for (int i=las[x];i!=-1;i=nxt[i])

              if (dis[to[i]]+1==dis[x] && num[i]>0) //Distance label, increasing traffic must satisfy the shortest path property, and this side has a value

              {

                     int now=dfs(to[i],min(s-have,num[i]));

                     num[i]-=now; num[i^1]+=now; //i^1 is the reverse edge number of to[i]->x, realized by saving the edge

                     have+=now; //Update storage traffic

                     if (have==s) return s; //If the flow is already full, return directly to prevent the distance label from being changed by impossible flow

              }

       if (--gap[dis[x]]==0) dis[1]=n; //If there is a gap in the distance label, it is impossible to flow again

       gap[++dis[x]]++;//Update the distance label

       return have;

}

int main()

{

       scanf("%d%d%d%d",&n,&m,&S,&T);

       memset(las,255,sizeof(las));

       memset(nxt,255,sizeof(nxt));

       for (int i=1;i<=m;i++)

       {

              int x,y; long long z;

              scanf("%d%d%lld",&x,&y,&z);

              insert(x,y,z);

              insert(y,x,0);   

       }

       long long sum=0;

       gap[0]=n;

       while (dis[S]<n) sum+=dfs(S,9000000000000000LL);

       printf("%lld\n",sum);

       return 0;

}

 

Routine & Skills & Precautions:

  1. The number of solutions for [l..r] is generally converted to [1..r]-[1..l-1].
  2. When it comes to interval coverage, think about the difference.
  3. When finding the minimum and maximum, think of dichotomy

4. The number of impossible = total number - the number of possible.

5. C++ rarely reports an error, so you have to pay attention to whether the array will cross the boundary, and whether to open long long.

6. When playing two points, you need to debug several times.

7. Pay attention to time allocation, and fight violence when you don't expect it.

8. Some searches that seem to be timed out can get a lot of points or even be cut off after adding pruning, so search should be pruned as much as possible, such as maximum and minimum value pruning, legality pruning, memorization, etc.

9. Pay attention to those strange special data in the data range.

10. The priority of bit operations in C++ is very low, so it is best to add parentheses.

11. To do the questions, you need to read the questions several times. When you want to do it, you must first understand the examples.

12. For some questions that need to be modeled, you can go to the model every few times when you are stuck, because the model is very slow.

13. Calling arrays is also relatively slow, at least slower than using variables directly, so don't call arrays if you can use variables often.

14. Remember to initialize.

15. When the space permits, don’t be stingy with the space consumed by long long. If you feel that the value may be relatively large, you can use long long.

16. When encountering a real number type, use double (pascal's extended) directly to prevent the precision from being stuck.

17. The line segment tree space should be 4n. That is to say, 100,000 numbers need to be stored in 400,000 spaces.

18. If the data is very large, it seems that the questions that can only be passed by O(1) are generally formula conclusion questions. If you can’t deduce the formula, you can use violence to find the law.

19. Sqrt must open cmath. Although it can be passed by only opening the algorithm on the compiler, it will be wrong if it is submitted.

20. Do not use variable names spelled in English such as get, last, next, etc., and do not use x0, y0, x1, y1 and the like when opening the cmath library. Because compilation errors may occur under different compilation environments.

 

 

Guess you like

Origin blog.csdn.net/jz_terry/article/details/109458507