Algorithm improvement course template

Keywords: Algorithm Dynamic Programming

Algorithm improvement course template

Chapter 1 dynamic programming

275. Slip of paper (Digital triangle model)

The note has to be passed to each other through many students. Obuchi sits in the upper left corner of the matrix, coordinates (1,1), and Xiaoxuan sits in the lower right corner of the matrix, coordinates (m,n).
The note from Xiaoyuan to Xiaoxuan can only be passed down or right, and the note from Xiaoxuan to Xiaoyuan can only be passed up or left
During the activity, Obuchi hopes to pass a note to Xiaoxuan and hope Xiaoxuan will reply to him.
Each student in the class can help them pass, but will only help them once, that is, if this person helps when Xiaoxuan hands Xiaoxuan a note, he will not help when Xiaoxuan hands it to Xiaoyuan, and vice versa
Another thing to note is that each student in the class is willing to help with varying degrees of favor (Note: the degree of kindness of Obuchi and Xiaoxuan is not defined, and it is expressed by 0 when entering). It can be expressed by a natural number of 0 ∼ 100. The larger the number, the better.
Obuchi and Xiaoxuan hope to find students with a high degree of kindness to help pass the note, that is, to find two transmission paths back and forth, so as to maximize the sum of the kindness of the students on these two paths.
Now, please help Obuchi and Xiaoxuan find these two paths.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55;
int dp[N+N][N][N];
int n,m,mp[N][N];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)cin>>mp[i][j];
    //dp[2][1][1]=0;
    
    for(int k=3;k<=m+n-1;k++){
        for(int i1=1;i1<n;i1++){
            for(int i2=i1+1;i2<=n;i2++){
                
                int j1=k-i1,j2=k-i2;
                if(j1<=0||j1>m||j2<=0||j2>=m)continue;
                int &x=dp[k][i1][i2];
                int w=mp[i1][j1]+mp[i2][j2];
                x=max(x,dp[k-1][i1][i2]+w);
                x=max(x,dp[k-1][i1-1][i2]+w);
                x=max(x,dp[k-1][i1][i2-1]+w);
                x=max(x,dp[k-1][i1-1][i2-1]+w);
            }
        }
    }
    
    cout<<dp[n+m-1][n-1][n];
    //After walking k steps, i1 reaches the top of the end point and i2 reaches the bottom of the end point
    
}

1057. Stock trading IV (state machine model)

Set an array with length N, and the ith number in the array represents the price of a given stock on day i.

Design an algorithm to calculate the maximum profit you can make. You can complete up to k transactions.

Note: you cannot participate in multiple transactions at the same time (you must sell the previous shares before buying again). One buy and sell is one transaction.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n,k,dp[100010][151][2],w[100010];
int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>w[i];
    memset(dp,0xcf,sizeof dp);
    for(int i=0;i<=n;i++)dp[i][0][0]=0;
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=k;j++){
            dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]+w[i]);
            dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j-1][0]-w[i]);
        }
    }
    int ans=0;
    for(int i=0;i<=k;i++)ans=max(dp[n][i][0],ans);
    cout<<ans;
}

1064. Little king

In n × Put k kings on the chessboard of N. The king can attack 8 adjacent grids. Find the total number of schemes that make them unable to attack each other.

#include <iostream>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
int n,k;
const int N = 1<<10;
int dp[12][150][N];
vector<int>state;
vector<int>head[N];
bool check(int x){
    for(int i=0;i<n;i++){
        if( (x>>i&1)&&( x>>i+1 &1) )return 0;
    }
    return 1;
}
int count(int x){
    int ans=0;
    for(int i=0;i<n;i++){
        ans+=((x>>i )&1);
    }
    return ans;
}
signed main(){
    cin>>n>>k;
    for(int i=0;i<1<<n;i++){
        if(check(i))state.push_back(i);
    }
    
    for(int i=0;i<state.size();i++){
        for(int j=0;j<state.size();j++){
            int a=state[i],b=state[j];
            if((a&b)==0&&check(a|b)){
                head[i].push_back(j);
            }
        }
    }
    dp[0][0][0]=1;
    for(int i=1;i<=n+1;i++){
        for(int j=0;j<=k;j++){
            for(int b=0;b<state.size();b++){
                for(int a:head[b]){
                    int c=count(state[a]);
                    if(j>=c){
                        dp[i][j][b]+=dp[i-1][j-c][a];
                    }
                }
            }
        }
    }
    cout<<dp[n+1][k][0];
}

327. Corn fields

Farmer John's land is owned by M × Composed of N small squares, now he wants to plant corn in the land.
Unfortunately, part of the land is sterile and cannot be planted.
Moreover, adjacent land cannot grow corn at the same time, that is, there will be no public edge between all squares planting corn.
Now, given the size of the land, please find out how many planting methods there are.
Nothing on the land is a way.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1<<12;
const int mod=1e8;
int m,n;
int dp[15][N];
int g[N];
vector<int>state;
vector<int>head[N];
bool check(int s){
    for(int i=0;i<n;i++){
        if((s>>i&1)&&(s>>i+1&1))return 0;
    }
    return 1;
}
int main(){
    cin>>m>>n;
    for(int i=0;i<1<<n;i++){
        if(check(i))state.push_back(i);
    }
    
    for(int i=1;i<=m;i++){
        for(int j=0;j<n;j++){
            //cin>>mp[i][j];
            int t;
            cin>>t;
            g[i]+=!t<<j;
            
        }
    }
    for(int i=0;i<state.size();i++){
        for(int j=0;j<state.size();j++){
            int a=state[i];
            int b=state[j];
            if(a&b)continue;
            head[i].push_back(j);
        }
    }
    dp[0][0]=1;
    for(int i=1;i<=m+1;i++){
        for(int a=0;a<state.size();a++){
            for(int b:head[a]){
                if(state[a]&g[i])continue;
                dp[i][a]+=dp[i-1][b];
            }
        }
    }
    cout<<dp[m+1][0]%mod;
}

292. Artillery positions

The generals plan how to deploy artillery units. On the premise of preventing accidental injury (ensuring that no two artillery units can attack each other, that is, no artillery unit is within the attack range of other artillery units), at most our artillery units can be placed in the whole map area.

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 10, M = 1 << 10;

int n, m;
int g[1010];
int f[2][M][M];
vector<int> state;
int cnt[M];

bool check(int state)
{
    for (int i = 0; i < m; i ++ )
        if ((state >> i & 1) && ((state >> i + 1 & 1) || (state >> i + 2 & 1)))
            return false;
    return true;
}

int count(int state)
{
    int res = 0;
    for (int i = 0; i < m; i ++ )
        if (state >> i & 1)
            res ++ ;
    return res;
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j < m; j ++ )
        {
            char c;
            cin >> c;
            g[i] += (c == 'H') << j;
        }

    for (int i = 0; i < 1 << m; i ++ )
        if (check(i))
        {
            state.push_back(i);
            cnt[i] = count(i);
        }

    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j < state.size(); j ++ )
            for (int k = 0; k < state.size(); k ++ )
                for (int u = 0; u < state.size(); u ++ )
                {
                    int a = state[j], b = state[k], c = state[u];
                    if (a & b | a & c | b & c) continue;
                    if (g[i] & b | g[i - 1] & a) continue;
                    f[i & 1][j][k] = max(f[i & 1][j][k], f[i - 1 & 1][u][j] + cnt[b]);
                }

    int res = 0;
    for (int i = 0; i < state.size(); i ++ )
        for (int j = 0; j < state.size(); j ++ )
            res = max(res, f[n & 1][i][j]);

    cout << res << endl;

    return 0;
}

524. Angry birds

Kiana has recently become addicted to a magical game.

In short, the game is played on a plane.

A catapult is located at (0,0). Every time Kiana can use it to launch a red bird into the first quadrant. The flight trajectory of the birds is a curve shaped like y=ax2+bx , where , A and B , are the parameters specified by Kiana and must meet , a < 0.

When the bird falls back to the ground (i.e. the , x , axis), it will disappear instantly.

In a level of the game, there are ^ n ^ green pigs in the first quadrant of the plane, and the coordinates of ^ i ^ pig are (xi,yi).

If the flight path of a bird passes (xi, yi), the , i , pig will be destroyed, and the bird will continue to fly along the original path;

If a bird's flight path does not pass through (xi, yi), the whole flight process of the bird will not have any impact on the {i} pig.

For example, if two piglets are located at (1,3) and (3,3), Kiana can choose to launch a bird with a flight trajectory of y = − x2+4x, so that the two piglets will be destroyed by the bird together.

The purpose of this game is to destroy all pigs by launching birds.

Each level of this magical game is very difficult for Kiana, so Kiana also entered some mysterious instructions to make it easier for her to complete the game.

These instructions will be detailed in the input format.

Assuming that the game has a total of {T} levels, Kiana now wants to know how many birds need to be launched for each level to destroy all pigs.

Since she can't count, I hope you can tell her.

Note: in addition to the original NOIP data, this topic also contains enhanced data.

Input format
The first line contains a positive integer T, which represents the total number of levels in the game.

Enter the information of these T levels in turn.

The first line of each level contains two non negative integers n and m, which respectively represent the number of pigs in the level and the mysterious command type input by Kiana.

In the next n lines, line I contains two positive real numbers (xi,yi), indicating that the coordinates of the i-th pig are (xi,yi). The data ensures that there are no two pigs with exactly the same coordinates in the same level.

#include<bits/stdc++.h>
#define x first
#define y second
#define eps 1e-12
using namespace std;

typedef pair<double, double> PDD;
PDD p[18];
int line[18][18],f[1<<18],n,m,t;
int cmp(double x, double y)
{
    if (abs(x - y) < eps) return 0;
    if (x < y) return -1;
    return 1;
}
int main(){
    cin>>t;
    while(t--){
        memset(line ,0,sizeof line);
        //memset(p,0,sizeof p);
        cin>>n>>m;
        for(int i=0;i<n;i++){
            cin>>p[i].x>>p[i].y;
        }
        for(int i=0;i<n;i++){
            line[i][i]=1<<i;
            for(int j=0;j<n;j++){
                if(i==j)continue;
                double x1=p[i].x,y1=p[i].y;
                double x2=p[j].x,y2=p[j].y;
                double a=(y1/x1-y2/x2)/(x1-x2);
                //if(a-eps>=0)continue;
                if(cmp(a,0)>=0)continue;
                double b=y1/x1-a*x1;
                int state=0;
                for(int k=0;k<n;k++){
                    double xx=p[k].x;
                    double y=p[k].y;
                    double yy=a*xx*xx+b*xx;
                    //if(yy-eps  < y <  yy+eps)state|=1<<k;
                    if(!cmp(y,yy))state|=1<<k;
                }
                line[i][j]=state;
                line[j][i]=state;
            }
        }
        memset(f,0x3f,sizeof f);
        //After preprocessing, now use state dp to optimize
        f[0]=0;
        for(int i=0;i<1<<n;i++){
            int x=0;
            for(int j=0;j<n;j++){
                if(! (i>>j&1) ){
                    x=j;
                    break;
                }
            }
            for(int j=0;j<n;j++){
                f[i|line[x][j] ]=min(f[i|line[x][j]],f[i]+1);
            }
        }
        cout<<f[(1<<n)-1]<<endl;
        
    }
}

3300. Food transportation

There are many hotels in T city. These hotels have different needs for different kinds of food materials. Lailai company is responsible for transporting food materials to these hotels every day.
Due to the large number of hotels, how to plan the transportation route has become a very important problem. As a consultant of Lailai company, please help them solve this difficult problem.
There are N hotels in T City, which are connected by N − 1 two-way roads. All hotels and roads form a tree.
Different roads may have different lengths, and the time required for transport vehicles to pass through the road is affected by the length of the road.
In T City, there are K mainstream ingredients.
Lailai company has K vehicles, and each vehicle is responsible for the distribution of one kind of food material. There are no multiple vehicles delivering the same food material.
Due to the different characteristics of different hotels, the demand for food materials in different hotels is also different. For example, hotel 1 may only need the first and fifth kinds of food materials, and hotel 2 needs all K kinds of food materials.
Lai Lai company transports food materials to these companies every day.
For the vehicle transporting the i-type food, this vehicle can start from any hotel and then transport the food to all hotels that need the i-type food.
Assuming that the loading and unloading of food materials during transportation does not take time, the transport vehicle is sufficient to fill all the required food materials at the time of departure, and the weight of food materials does not affect the speed of the transport vehicle.
In order to improve the distribution efficiency, the K cars can start from different hotels.
However, since T City pays special attention to food safety, food safety inspection is required for each vehicle before delivery.
In view of the shortage of personnel for food safety inspection, a maximum of M inspection points can be set.
Now Lailai company needs you to formulate a transportation plan: select no more than M hotels to set up food safety checkpoints, determine which checkpoint each transport vehicle starts from, and plan the route of each transport vehicle.
Assuming that all food transporters leave at the same time after food safety inspection, please formulate a transportation scheme to minimize the maximum waiting time of all hotels.
The waiting time of the hotel is calculated from the departure of the transport vehicle until all the required ingredients of the hotel are transported.
If a hotel does not need any ingredients, its waiting time is 0.
Input format
The first line contains three positive integers n, m and K. see the title description for the meaning.
Next N lines, each containing K integers. Each line of input describes the demand of the corresponding hotel for each kind of food material. 1 indicates that the corresponding food material is required, and 0 indicates that it is not required.
Next, N − 1 line, each line contains three integers u, v and W, indicating that there is a two-way road with travel time w connecting u Hotel and v Hotel.
Ensure that the input data is a tree, and the hotel number is from 1 to N.

#include <iostream>
#include <cstring>
#include <algorithm>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
const int N = 110, M = 10, S = 1 << M;

int n, m, k;
int need[N][M];
int h[N], e[N * 2], w[N * 2], ne[N * 2], idx;
int d[N][M];
int f[S], state[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

PII dfs(int u, int fa, int v)
{
    PII res(0, -1);
    if (need[u][v]) res.y = 0;
    for (int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        if (j == fa) continue;
        auto t = dfs(j, u, v);
        if (t.y != -1)
        {
            res.x += t.x + w[i] * 2;
            res.y = max(res.y, t.y + w[i]);
        }
    }
    return res;
}

bool check(int mid)
{
    memset(state, 0, sizeof state);
    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j < k; j ++ )
            if (d[i][j] <= mid)
                state[i] |= 1 << j;
    memset(f, 0x3f, sizeof f);
    f[0] = 0;
    for (int i = 0; i < 1 << k; i ++ )
        for (int j = 1; j <= n; j ++ )
            f[i | state[j]] = min(f[i | state[j]], f[i] + 1);
    return f[(1 << k) - 1] <= m;
}

int main()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j < k; j ++ )
            cin >> need[i][j];
    memset(h, -1, sizeof h);
    for (int i = 0; i < n - 1; i ++ )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c), add(b, a, c);
    }

    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j < k; j ++ )
        {
            auto t = dfs(i, -1, j);
            if (t.y != -1) d[i][j] = t.x - t.y;
        }

    int l = 0, r = 2e8;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }

    printf("%d\n", r);
    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/979737/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

529. Treasures

Xiao Ming, who participated in the archaeological excavation, got a treasure map. The treasure map marked n treasure houses buried deep underground, and also gave the m roads available for development between the N treasure houses and their lengths.  
Xiao Ming is determined to dig the treasures in all the treasure houses in person.
However, each treasure house is far from the ground, that is, it is very difficult to get through a road to a treasure house from the ground, while it is relatively easy to develop the road between treasure houses.
Xiao Ming's determination moved the sponsor of the archaeological excavation. The sponsor decided to sponsor him to open a channel from the ground to a treasure house for free. It was up to Xiao Ming to decide which treasure house to lead to.  
On this basis, Xiao Ming also needs to consider how to dig the road between the treasure houses.
The excavated road can pass freely without cost.
Every time a new road is dug, Xiao Ming will dig out the treasures of the treasure house that can be reached by the road together with the archaeological team.
In addition, Xiaoming doesn't want to develop useless roads, that is, the road between two excavated treasure houses doesn't need to be developed.
The cost of developing a new road is:
The length of this road × The number of treasure houses passed from the treasure house opened by the sponsor to the treasure house at the beginning of the road (including the treasure house opened by the sponsor and the treasure house at the beginning of the road).  
Please write a program to select the treasure house opened by the sponsor and the road dug later for Xiaoming, so as to minimize the total cost of the project, and output this minimum value.
Input format
In the first line, two positive integers , n , and , m separated by spaces represent the number of treasure houses and roads.
Next, there are three positive integers separated by spaces in line m, which are the numbers of the two treasure houses connected by a road (number 1 ∼ n) and the length v of the road.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 12, M = 1 << 12, INF = 0x3f3f3f3f;

int n, m;
int d[N][N];
int f[M][N], g[M];

int main()
{
    scanf("%d%d", &n, &m);

    memset(d, 0x3f, sizeof d);
    for (int i = 0; i < n; i ++ ) d[i][i] = 0;

    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        a --, b --;
        d[a][b] = d[b][a] = min(d[a][b], c);
    }

    for (int i = 1; i < 1 << n; i ++ )
        for (int j = 0; j < n; j ++ )
            if (i >> j & 1)
            {
                for (int k = 0; k < n; k ++ )
                    if (d[j][k] != INF)
                        g[i] |= 1 << k;
            }

    memset(f, 0x3f, sizeof f);
    for (int i = 0; i < n; i ++ ) f[1 << i][0] = 0;

    for (int i = 1; i < 1 << n; i ++ )
        for (int j = (i - 1); j; j = (j - 1) & i)
            if ((g[j] & i) == i)
            {
                int remain = i ^ j;
                int cost = 0;
                for (int k = 0; k < n; k ++ )
                    if (remain >> k & 1)
                    {
                        int t = INF;
                        for (int u = 0; u < n; u ++ )
                            if (j >> u & 1)
                                t = min(t, d[k][u]);
                        cost += t;
                    }

                for (int k = 1; k < n; k ++ ) f[i][k] = min(f[i][k], f[j][k - 1] + cost * k);
            }

    int res = INF;
    for (int i = 0; i < n; i ++ ) res = min(res, f[(1 << n) - 1][i]);

    printf("%d\n", res);
    return 0;
}

3735. Complete structural drawing

An undirected connected graph consisting of n points and m edges is given.
We want to turn it into a complete graph through a series of operations (that is, each pair of different vertices has exactly one edge connected).
During each operation, you can select one of the points, find all the points directly connected to it, and connect the edges between these points (if there are already edges between the two points, there is no need to connect them repeatedly).
How many operations can you change the whole graph into a complete graph?

#include<bits/stdc++.h>
#define x first
#define y second

using namespace std;
const int N = 22, M=1<<22;
typedef pair<int,int> PII;
int n,m;
int f[M];
int e[N];
PII g[M];
int main(){
    cin>>n>>m;
    if(2*m==n*(n-1)){
        puts("0");
        return 0;
    }
    memset(f,0x3f,sizeof f);
    for(int i=0;i<n;i++)e[i]=1<<i;
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        x--,y--;
        e[x]|=1<<y;
        e[y]|=1<<x;
    }
    for(int i=0;i<n;i++)f[e[i]]=1,g[e[i]]={0,i};
    //During each operation, you can select one of the points, find all the points directly connected to it, and connect the edges between these points
    for(int i=0;i<1<<n;i++){
        //Enumerate the point sets for each state connection
        for(int j=0;j<n;j++){
            if(f[i]==0x3f3f3f3f)continue;
            if(i>>j&1){//Cluster i is connected to point j
                int k=i|e[j];//The new larger regiment is obtained from the original regiment i and the upper small regiment j
                if(f[k]>f[i]+1){
                    f[k]=f[i]+1;//State k is obtained by connecting state i to point j
                    g[k]={i,j};//State k is obtained by connecting state i to point j
                }
            }
        }
    }
    int k=(1<<n)-1;
    cout<<f[k]<<endl;
    
    while(k){
        cout<<g[k].y+1<<" ";
        k=g[k].x;
    }
    //Recursive output, state k is state x before it is connected to j, so which state x is connected to which point?
    //Here we deal with recursion
    
}

1068. Combination of ring stones

The n heaps of stones will be discharged around the circular playground. Now the stones will be orderly combined into a pile.
It is stipulated that only two adjacent piles can be combined into a new pile at a time, and the number of stones in a new pile shall be recorded as the score of the combination.
Please write a program to read the number of piles n and the number of stones in each pile, and calculate as follows:
Select a scheme of merging stones to maximize the sum of n − 1 merging scores.
Select a scheme of merging stones to minimize the sum of n − 1 merging scores.
Input format
The first line contains the integer n, indicating that there are n heaps of stones.
The second line contains n integers representing the number of stones in each pile.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 440,INF=0x3f3f3f3f;
int f[N][N],g[N][N],n,w[N+N],maxv=-INF,minv=INF;
int sum[2*N];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i];
        w[i+n]=w[i];
        
    }
    for(int i=1;i<=n*2;i++)sum[i]=sum[i-1]+w[i];
    memset(f,-0x3f,sizeof f);
    memset(g,0x3f,sizeof g);
    for(int len=1;len<=n;len++){
        for(int l=1;l+len-1<=2*n;l++){
            int r=l+len-1;
            if(len==1)f[l][r]=g[l][r]=0;
            else{
                for(int k=l;k<r;k++){
                    f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]+sum[r]-sum[l-1]);
                    g[l][r]=min(g[l][r],g[l][k]+g[k+1][r]+sum[r]-sum[l-1]);
                }
            }
            
        }
    }
    for(int i=1;i<=n;i++){
        maxv=max(maxv,f[i][i+n-1]);
        minv=min(minv,g[i][i+n-1]);
    }
    cout<<minv<<endl<<maxv;
}

320. Energy Necklace

If the head of the former energy bead is marked with m and the tail is marked with R, and the head of the latter energy bead is marked with R and the tail is marked with N, the energy released after polymerization is m × r × N (Mars unit), the head of the newly produced bead is marked as m and the tail is marked as n.
When necessary, Mars people clamp two adjacent beads with suction cups and get energy through polymerization until there is only one bead left on the necklace.
Obviously, the total energy obtained by different polymerization sequences is different. Please design a polymerization sequence to maximize the total energy released by a necklace.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 202;
int w[N],dp[N][N];
int n;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i];
        w[i+n]=w[i];
    }
    //memset(dp,-0x3f,sizeof dp);
    //len indicates the number of nodes
    for(int len=3;len<=n+1;len++){
        for(int L=1;L+len-1<=2*n;L++){
            int R=L+len-1;
            for(int k=L+1;k<R;k++){
                dp[L][R]=max(dp[L][R],dp[L][k]+dp[k][R]+w[L]*w[k]*w[R]);
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++)ans=max(ans,dp[i][i+n]);
    cout<<ans<<endl;
    
}

479. Additive binary tree

Let the middle order traversal of a binary tree with n nodes be (1,2,3,..., n), where the numbers 1,2,3,..., n are the node numbers.

Each node has a score (all positive integers). Note that the score of the ith node is di, and each subtree of the tree and its subtree has a bonus. The bonus calculation method of any subtree (including the tree itself) is as follows:

Bonus points of left subtree of subtree × Bonus of right subtree of subtree + score of root of subtree

If a subtree is empty, the extra score is 1.

The bonus of a leaf is the score of the leaf node itself, regardless of its empty subtree.

Try to find a binary tree that conforms to the middle order and traverses (1,2,3,..., n) with the highest bonus.

Required output:

(1) The highest bonus of tree

(2) Preorder traversal of tree

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int w[100];
int tree[100][100];
int root[100][100];
int n;
int ans;
int dfs(int l,int r){
    if(tree[l][r])return tree[l][r];
    if(l==r)return w[l];
    if(l>r)return 1;
    for(int i=l;i<=r;i++){
        int t=dfs(l,i-1)*dfs(i+1,r)+w[i];
        if(t>tree[l][r]){
            tree[l][r]=t;
            root[l][r]=i;
        }
    }
    return tree[l][r];
}
void dg(int l,int r){
    if(l>r)return;
    if(l==r){printf("%d ",root[l][r]);return;}
    
    printf("%d ",root[l][r]);
    dg(l,root[l][r]-1);
    dg(root[l][r]+1,r);
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>w[i];
    for(int i=1;i<=n;i++)root[i][i]=i;
    cout<<dfs(1,n)<<endl;
    dg(1,n);
}

1069. Division of convex polygons (interval dp + high precision)

Given a convex polygon with n vertices, label the vertices from 1 to N, and the weight of each vertex is a positive integer.

The convex polygon is divided into N − 2 disjoint triangles. For each triangle, the weights of its three vertices are multiplied to obtain a weight product. Try to find out the sum of the vertex weight products of all triangles.
Output only one line, which is the minimum value of the sum of the vertex weight products of all triangles.
This answer needs high precision

n = int(input())
a = list(map(int,input().split()))
w = [0]+a 
f = [[0 for _ in range(n+1)] for _ in range(n+1)]
for length in range(3,n+1):
    for l in range(1,n-length+2):
        r = l + length - 1
        f[l][r] = float('inf')
        for k in range(l+1,r):
            f[l][r] = min(f[l][r],f[l][k]+f[k][r]+w[l]*w[k]*w[r])

print(f[1][n])

Author: IdealDragon
 Link: https://www.acwing.com/activity/content/code/content/134559/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 55, M = 35, INF = 1e9;

int n;
int w[N];
LL f[N][N][M];

void add(LL a[], LL b[])
{
    static LL c[M];
    memset(c, 0, sizeof c);
    for (int i = 0, t = 0; i < M; i ++ )
    {
        t += a[i] + b[i];
        c[i] = t % 10;
        t /= 10;
    }
    memcpy(a, c, sizeof c);
}

void mul(LL a[], LL b)
{
    static LL c[M];
    memset(c, 0, sizeof c);
    LL t = 0;
    for (int i = 0; i < M; i ++ )
    {
        t += a[i] * b;
        c[i] = t % 10;
        t /= 10;
    }
    memcpy(a, c, sizeof c);
}

int cmp(LL a[], LL b[])
{
    for (int i = M - 1; i >= 0; i -- )
        if (a[i] > b[i]) return 1;
        else if (a[i] < b[i]) return -1;
    return 0;
}

void print(LL a[])
{
    int k = M - 1;
    while (k && !a[k]) k -- ;
    while (k >= 0) cout << a[k -- ];
    cout << endl;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> w[i];

    LL temp[M];
    for (int len = 3; len <= n; len ++ )
        for (int l = 1; l + len - 1 <= n; l ++ )
        {
            int r = l + len - 1;
            f[l][r][M - 1] = 1;
            for (int k = l + 1; k < r; k ++ )
            {
                memset(temp, 0, sizeof temp);
                temp[0] = w[l];
                mul(temp, w[k]);
                mul(temp, w[r]);
                add(temp, f[l][k]);
                add(temp, f[k][r]);
                if (cmp(f[l][r], temp) > 0)
                    memcpy(f[l][r], temp, sizeof temp);
            }
        }

    print(f[1][n]);

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/124469/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

321. Chessboard segmentation

Put an 8 × The chessboard of 8 is divided as follows: cut off a rectangular chessboard from the original chessboard and make the rest also rectangular, and then continue to divide the rest. After cutting (n − 1) times, there are n rectangular chessboards together with the last remaining rectangular chessboard. (each cutting can only be carried out along the edge of the chessboard grid) each grid on the chessboard has a score, and the total score of a rectangular chessboard is the sum of the scores of each grid.
Now we need to divide the chessboard into n rectangular chessboards according to the above rules, and minimize the mean square deviation of the total score of each rectangular chessboard.

#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 15, M = 9;
const double INF = 1e9;

int n, m = 8;
int s[M][M];
double f[M][M][M][M][N];
double X;

int get_sum(int x1, int y1, int x2, int y2)
{
    return s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1];
}

double get(int x1, int y1, int x2, int y2)
{
    double sum = get_sum(x1, y1, x2, y2) - X;
    return (double)sum * sum / n;
}

double dp(int x1, int y1, int x2, int y2, int k)
{
    double &v = f[x1][y1][x2][y2][k];
    if (v >= 0) return v;
    if (k == 1) return v = get(x1, y1, x2, y2);

    v = INF;
    for (int i = x1; i < x2; i ++ )
    {
        v = min(v, get(x1, y1, i, y2) + dp(i + 1, y1, x2, y2, k - 1));
        v = min(v, get(i + 1, y1, x2, y2) + dp(x1, y1, i, y2, k - 1));
    }

    for (int i = y1; i < y2; i ++ )
    {
        v = min(v, get(x1, y1, x2, i) + dp(x1, i + 1, x2, y2, k - 1));
        v = min(v, get(x1, i + 1, x2, y2) + dp(x1, y1, x2, i, k - 1));
    }

    return v;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= m; i ++ )
        for (int j = 1; j <= m; j ++ )
        {
            cin >> s[i][j];
            s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
        }

    X = (double)s[m][m] / n;
    memset(f, -1, sizeof f);
    printf("%.3lf\n", sqrt(dp(1, 1, 8, 8, n)));

    return 0;
}

1072. Longest path of tree

Given a tree, the tree contains n nodes (No. 1~n) and N − 1 undirected edges, and each edge has a weight.
Now please find the longest path in the tree.
In other words, find a path so that the distance between the points at both ends of the path is the farthest.
Note: a path can contain only one point.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010, M = N * 2;

int n;
int h[N], e[M], w[M], ne[M], idx;
int ans;

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

int dfs(int u, int father)
{
    int dist = 0; // Indicates the maximum length to go down from the current point
    int d1 = 0, d2 = 0;

    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (j == father) continue;
        int d = dfs(j, u) + w[i];
        dist = max(dist, d);

        if (d >= d1) d2 = d1, d1 = d;
        else if (d > d2) d2 = d;
    }

    ans = max(ans, d1 + d2);

    return dist;
}

int main()
{
    cin >> n;

    memset(h, -1, sizeof h);
    for (int i = 0; i < n - 1; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }

    dfs(1, -1);

    cout << ans << endl;

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/125605/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

1073. The center of the tree

Given a tree, the tree contains n nodes (No. 1~n) and N − 1 undirected edges, and each edge has a weight.

Please find a point in the tree to make it the farthest and closest to other nodes in the tree.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010, M = N * 2, INF = 0x3f3f3f3f;

int n;
int h[N], e[M], w[M], ne[M], idx;
int d1[N], d2[N], p1[N], up[N];
bool is_leaf[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}

int dfs_d(int u, int father)
{
    d1[u] = d2[u] = -INF;
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (j == father) continue;
        int d = dfs_d(j, u) + w[i];
        if (d >= d1[u])
        {
            d2[u] = d1[u], d1[u] = d;
            p1[u] = j;
        }
        else if (d > d2[u]) d2[u] = d;
    }

    if (d1[u] == -INF)
    {
        d1[u] = d2[u] = 0;
        is_leaf[u] = true;
    }

    return d1[u];
}

void dfs_u(int u, int father)
{
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (j == father) continue;

        if (p1[u] == j) up[j] = max(up[u], d2[u]) + w[i];
        else up[j] = max(up[u], d1[u]) + w[i];

        dfs_u(j, u);
    }
}

int main()
{
    cin >> n;
    memset(h, -1, sizeof h);
    for (int i = 0; i < n - 1; i ++ )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }

    dfs_d(1, -1);
    dfs_u(1, -1);

    int res = d1[1];
    for (int i = 2; i <= n; i ++ )
        if (is_leaf[i]) res = min(res, up[i]);
        else res = min(res, max(d1[i], up[i]));

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

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/125606/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

1075. Digital conversion (approximate sum)

If the sum of divisors y (excluding itself) of a number x is smaller than itself, then x can become y and y can become X.

For example, 4 can become 3 and 1 can become 7.

Limit all digital transformations to a positive integer range of no more than n, and find the maximum number of transformation steps for continuous digital transformation without repeated numbers.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50005;
int h[N],ne[N],e[N],n,st[N],sum[N],idx;
int ans;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

int dfs(int u){
    int d1=0,d2=0;
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        int d=dfs(j)+1;
        if(d>=d1)d2=d1,d1=d;
        else if(d>d2)d2=d;
        
    }
    ans=max(ans,d1+d2);
    return d1;
}

int main(){
    cin>>n;
    memset(h, -1, sizeof h);
    //Using the idea of ESH sieve method, we don't directly find the sum of divisors of a number, but find what can divide the number
    //i enumerates divisors, j is a multiple, and sum[i*j]+=i
    //Why not + = (i+j), because when i=j is enumerated, it will be added again, and an error will occur
    for(int i=1;i<n;i++)
        for(int j=2;j<=n/i;j++)
            sum[i*j]+=i;
    for(int i=1;i<=n;i++)
        if(i>sum[i])add(sum[i],i),st[i]=1;
    
    // for(int i=1;i<=n;i++){
    //     if(!st[i])dfs(i);
    // }
    dfs(1);
    cout<<ans;
        
    
}

1074. Binary apple tree

There is a binary apple tree. If the branch is forked, it must be forked, that is, there is no node with only one son.
The tree has n nodes, numbered from 1 to N, and the root number must be 1.
We describe the position of a branch with the node number connected at both ends of a branch.
An apple tree has too many branches and needs to be pruned. However, some branches have apples. Given the number of branches to be retained, ask how many apples can be retained at most.
The reservation here refers to the final connection with point 1.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
int h[N],e[N*2],w[N*2],ne[N*2],idx,a,b,c,n,k,m,dp[N][N];

void add(int a,int b,int c){
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u,int father){
    for(int i=h[u];~i;i=ne[i]){
        int  j=e[i];
        if(j==father)continue;
        dfs(j,u);
        for(int money=m;money;money--){
            for(int k=0;k<money;k++){
                dp[u][money]=max(dp[u][money] , dp[u][money-k-1]+dp[j][k]+w[i]);
            }
        }
        
    }
}


int main(){
    cin>>n>>m;
    memset(h,-1,sizeof h);
    for(int i=0;i<n-1;i++){
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    dfs(1,-1);
    printf("%d\n",dp[1][m]);
}

323. Strategy games

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1510;
int h[N],e[N*2],w[N*2],ne[N*2],idx,n,st[N],dp[N][2];
void add(int a,int b,int c){
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u){
    dp[u][0]=0;
    dp[u][1]=1;
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        dfs(j);
        dp[u][0]+=dp[j][1];
        dp[u][1]+=min(dp[j][1],dp[j][0]);
    }
}

int main(){
    while(scanf("%d",&n)==1){
        idx=0;
        memset(h,-1,sizeof h);
        memset(st,0,sizeof st);
        int id,cnt;
        for(int i=1;i<=n;i++){
            scanf("%d:(%d)",&id,&cnt);
            while(cnt--){
                int x;
                cin>>x;
                
                add(id,x,1);
                st[x]=1;
            }
        }
        int root=0;
        while(st[root])root++;
        dfs(root);
        cout<<min(dp[root][0],dp[root][1])<<endl;
        
    }
}

1077. Palace guards

After the incident of the prince of Taiping, Lu Xiaofeng became the first-class bodyguard specially hired by the emperor.

The palace is distributed in the shape of a tree. The palace can be regarded as a node in the tree. If there is a road directly connected between the two palaces, the road is regarded as an edge in the tree.

It is known that the guards guarding a palace can not only observe the situation of the palace, but also observe the situation of other palaces directly connected to the road of the palace.

The interior is heavily guarded, with three steps and one post and five steps and one sentry. Each palace should be guarded around the clock. The cost of arranging detention centers in different palaces is different.

However, Lu Xiaofeng had insufficient funds and could not place left behind guards in every palace anyway.

Help Lu Xiaofeng arrange bodyguards to minimize the cost on the premise of guarding all the palaces.

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1501;
int h[N],w[N],ne[N],e[N],idx,n,st[N];
int dp[N][3];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs(int u){
    dp[u][2]=w[u];
    int sum=0;
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        dfs(j);
        dp[u][0]+=min(dp[j][1],dp[j][2]);
        dp[u][2]+=min(min(dp[j][0],dp[j][1]),dp[j][2]);
        sum+=min(dp[j][1],dp[j][2]);
    }
    dp[u][1]=1e9;
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        dp[u][1]=min(dp[u][1], sum-min(dp[j][1],dp[j][2]) + dp[j][2]);
    }
}

int main(){
    cin>>n;
    int id,x,cnt;
    memset(h, -1, sizeof h);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&id,&x,&cnt);
        w[id]=x;
        while(cnt--){
            int a;
            cin>>a;
            add(id,a);
            st[a]=1;
        }
    }
    int root=1;
    while(st[root])root++;
    dfs(root);
    cout<<min( dp[root][1] ,dp[root][2])<<endl;
}

1081. Number of degrees

Find the number of integers in a given interval [X,Y] that meet the following conditions: this number is exactly equal to the sum of the integer powers of K unequal B.
For example, if x = 15, y = 20, k = 2 and B = 2, there are and only the following three numbers to meet the meaning of the question:

17=2 ^4+2 ^0
18=2 ^4+2 ^1
20=2 ^4+2 ^2
Input format
The first line contains two integers X and Y, and the next two lines contain integers K and B.

Output format
Contains only one integer, indicating the number of qualified numbers.
This is a digital dp problem. The key to digital dp problem is classified discussion.

First, we decompose the number n into B-ary, store the number on each bit in an array, and then discuss it from high to low,
First, there are three cases for the i-th digit x

x = 0: only 0 can be taken on the i-bit, so it is OK to directly discuss the i-1 bit
x = 1: when 0 is taken on the i-bit, the following i-1 bits can be taken at will. When 1 is taken, the following i-1 bits can be taken on the premise that it is less than the number of topics, and k-last-1 ones can be taken,
X > 1: then 1 and 0 can be taken on the i-bit, and the following i-1 bit can be taken arbitrarily.
Here, the difference between the random selection of i-1 bits and the discussion of i-1 bits is reflected in that the previous one can directly use the combination number f[i-1][k-last], and then it needs to enter the loop for discussion.

Finally, we will discuss the last bit separately. If all k 1s have been taken for the last bit, that is, k==last, we can do res + +.

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 35;

int K, B;
int f[N][N];

void init(){//Find combination number
    for(int i=0;i<=N;i++){
        for(int j=0;j<=i;j++){
            if(!j)f[i][j]=1;
            else f[i][j]=f[i-1][j-1]+f[i-1][j];
        }
    }
}


int dp(int n){
    if (!n) return 0;//If n==0, put it back directly
    vector<int> v;
    while (n) v.push_back(n % B), n /= B;
    int res=0;
    int last=0;//Indicates how many 1s have been taken

    for(int i=v.size()-1;i>=0;i--){//Discuss each digit from the highest order
        int x=v[i];
        if(x){
            res += f[i][K - last];//Add the number of combinations when the i-th bit takes 0, that is, the number of k-last 1 for the following I-bit
            if (x > 1)//If x > 1, it can be expressed directly by combinatorial number without discussion, that is, when i bit takes 1, the following i bit arbitrarily takes k-last-1 1
            {
                if (K - last - 1 >= 0) res += f[i][K - last - 1];
                break;
            }
            else//If x==1, it is necessary to discuss when the i bit takes 1. The latter i bit cannot be taken casually, which is not a combinatorial number
            {
                last ++ ;
                if (last > K) break;
            }
        }
       if (!i && last == K) res ++ ;// For the last one to consider
    }
    return res;
}

int main()
{
    init();

    int l, r;
    cin >> l >> r >> K >> B;

    cout << dp(r) - dp(l - 1) << endl;

    return 0;
}

1082. Digital games

Someone named a non decreasing number. This number must meet the non decreasing relationship from left to right, such as 123446.

Now we decide to play a game, specify an integer closed interval [a,b], and ask how many non decreasing numbers are in this interval.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=15;

int f[maxn][maxn];
///f[i][j] represents a set of non decreasing numbers with the highest bit being j and a total of I bits
void init()
{
    for(int i=0;i<=9;i++) f[1][i]=1;

    for(int i=2;i<maxn;i++)
        for(int j=0;j<=9;j++)//j to start with 0
            for(int k=j;k<=9;k++)
                f[i][j]+=f[i-1][k];
}

int dp(int n)
{
    if(!n) return 1;

    vector<int>nums;
    while(n) nums.push_back(n%10),n/=10;
    int res=0;//Number of schemes
    int last=0;//Keep some prefix information. What's the last number
    ///Enumerate from maximum
    for(int i=nums.size()-1;i>=0;i--)
    {
        int x=nums[i];//x is the current digit
        for(int j=last;j<x;j++)  It's better than the next one>=Last, so from last Start enumeration,Enumerate up to x,last It is the upper bit, that is, the highest bit. The enumeration of the next bit is limited
            res+=f[i+1][j];    ///The node at the left end has i+1 digits (because the subscript of the first bit is 0)

        if(x<last) break;//If the current number is smaller than the previous one, then none of the following ones is tenable. Just break out

        last=x;

        if(!i) res++; //If the last number can be reached smoothly, it means that each number in the rightmost section of the tree is less than or equal to the previous digit, so++
    }

    return res;
}

int main(void)
{
    init();
    int l,r;
    while(cin>>l>>r)
    {
         cout<<dp(r)-dp(l-1)<<endl;
    }
return 0;    
}

1083. Windy number

Windy defines a kind of windy number: a positive integer without leading zero and the difference between two adjacent numbers is at least 2 is called windy number.

Windy wants to know how many windy numbers are there between A and B, including A and B?
Analysis
You can see that the range of A and B is very large, but think about it. Their digits will not exceed 9. Isn't this just in line with the routine of digital DP?

First, specify how to design this state:
The value of each bit is related to the previous one. It also explains that when we get to the pos layer, this layer is related to the pos+1 layer, then we
Let f[pos][las] be the number of qualified numbers starting with las in the pos layer

Interpretation process:
Enumeration always has a limit, which is the boundary. We need to decompose each bit of the boundary and mark whether there is a variable
Maximum limit
int ed=(limit) ? k[dep]:9;

Actually, it's easy to understand.
For example, you can eat 5432 drumsticks. You have eaten 5000. How many more can you eat? 432. That is, the maximum number in the hundredth is 4.

Then according to this scope, plus the judgment required by the topic

ret+=dfs(lead&&(!i),limit&&(i==ed),dep-1,i);

//#pragma GCC optimize(3,"inline","Ofast","fast-math","no-stack-protector","unroll-loops")
//#pragma GCC target("sse","sse2","sse3","sse4","avx","avx2","popcnt")
//Manual optimization
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>

#define RG register
#define ll long long
#define INF 0x3f3f3f3f

using namespace std;

const int N=35,M=11;

int f[N][M],k[N];//Limit per bit
int a,b;//Range

inline int dfs(bool lead,bool limit,int dep,int las)
{
    if(!dep) return 1;
    if(!lead&&!limit&&(~f[dep][las])) return f[dep][las];

    int ret=0;
    int ed=(limit) ? k[dep]:9;
//  printf("1___ ed= %d\n",ed);
    for (int i=0;i<=ed;i++)
        if(lead||abs(i-las)>=2)
        //As long as the difference between the currently selected number and the last one is 2
        {
            ret+=dfs(lead&&(!i),limit&&(i==ed),dep-1,i);
//          printf("2___ ret= %d\n",ret);
        }


    if(!lead&&!limit) f[dep][las]=ret;
    return ret;
}

inline int dp(int n)
{
    int cnt=0;
    if(!n) return 1;
    while(n) k[++cnt]=n%10,n/=10;//Decompose each bit

    int res=0;
    for (int i=0;i<=k[cnt];i++)
        res+=dfs((!i),i==k[cnt],cnt-1,i);

    return res;
}

int main()
{
    memset(f,-1,sizeof(f));//initial
    scanf("%d%d",&a,&b);

    printf("%d\n",dp(b)-dp(a-1));
    //Difference thought
    return 0;
}

Author: Dear_You
 Link: https://www.acwing.com/solution/content/5813/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

1084. Digital game II

Someone also named a modulus, which must satisfy that the sum of the numbers mod N is 0.

Now we're going to play the game again. Specify an integer closed interval [a.b] and ask how many modulus values are in this interval.
For this question, suppose we enumerate the i-th digit and the number on the i-th digit is x, then for the i-th digit j in the answer, two types of numbers can be filled in:

1.0~x-1
We use last to represent the sum of the numbers on the previous digits so far. For this, the current i-th digit is j, and the sum of the previous digits is last, then
The relationship between sum of the last i digits (including j) and last is (last+sum)%N == 0, then the result of sum%N is equivalent to (- last)%N,
So res += f[i+1][j][(-last%N)]; (the processing of F array will be mentioned later)
2.x
If j is filled with X, there is no need to enumerate. last += x, and then enumerate the next bit
f array processing
f[i][j][k] represents the number of I bits in total, the highest digit is j, and all bit numbers and modulo N results are K

State transition: since bit i is already j and the sum modulus N of all numbers is k, we consider bit i-1 and assume that bit i-1 is x. since j already knows,
Then the result of the sum of the remaining i-1 digits modulo n is (k-j)%N, and the state transition equation is:

f[i][j][k]=∑N−1k=0∑9x=0f[i−1][x][mod(k−j,N)]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 12, M = 102;

int f[N][10][M];  //f[i][j][k] indicates that there are a total of I bits, the highest digit is j, and the number of all bits and modulo p-bit K
int p;

int mod(int u,int v){
    return (u%v+v)%v;  //The% of c + + will get a negative number, which needs to be offset
}

void init(){
    memset(f,0,sizeof f);   //Multiple groups of test data, f array to be cleared
    for(int i = 0; i<=9; i++) f[1][i][i%p]++;

    for(int i = 2; i<N; i++)
        for(int j = 0; j<=9; j++)
            for(int k = 0; k<p; k++)
                for(int x = 0; x<=9; x++)
                    f[i][j][k] += f[i-1][x][mod(k-j,p)];
}

int dp(int n){
    if(!n) return 1;
    int res = 0,last = 0;

    vector<int> a;
    while(n) a.push_back(n%10),n/=10;

    int len = a.size()-1;
    for(int i = len; i>=0; --i){
        int x =a[i];    
        for(int j = 0; j<x; j++)  //Position i: 0~x-1
            res += f[i+1][j][mod(-last,p)]; //0~i bits, so there are i+1 bits in total

        last += x;
        if(!i && last % p == 0) res ++; 
    }
    return res;
}
int main()
{

    int l,r;
    while(cin>>l>>r>>p){
        init();
        cout<<dp(r)-dp(l-1)<<endl;
    }

    return 0;
}

1085. Don't 62

Hangzhou people call those silly and sticky people 62 (sound: laoer).

Hangzhou traffic administration often expands some taxi license plates. Recently, a good news came out. In the future, the license plate will no longer contain unlucky numbers. In this way, the psychological barriers of individual taxi drivers and passengers can be eliminated and the public can be served more safely.

Unlucky numbers are all numbers containing 4 or 62. For example, 62315734188914 are unlucky numbers. However, 61152 contains 6 and 2, but it is not a consecutive number, so it does not belong to the list of unlucky numbers.

Your task is to infer how many new taxis the traffic authority will actually license in the future for each given license plate number range [n,m].

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 35;

int f[N][10];

void init()
{
    for (int i = 0; i <= 9; i ++ )
        if (i != 4)
            f[1][i] = 1;

    for (int i = 1; i < N; i ++ )
        for (int j = 0; j <= 9; j ++ )
        {
            if (j == 4) continue;
            for (int k = 0; k <= 9; k ++ )
            {
                if (k == 4 || j == 6 && k == 2) continue;
                f[i][j] += f[i - 1][k];
            }
        }
}

int dp(int n)
{
    if (!n) return 1;

    vector<int> nums;
    while (n) nums.push_back(n % 10), n /= 10;

    int res = 0;
    int last = 0;
    for (int i = nums.size() - 1; i >= 0; i -- )
    {
        int x = nums[i];
        for (int j = 0; j < x; j ++ )
        {
            if (j == 4 || last == 6 && j == 2) continue;
            res += f[i + 1][j];
        }

        if (x == 4 || last == 6 && x == 2) break;
        last = x;

        if (!i) res ++ ;
    }

    return res;
}

int main()
{
    init();

    int l, r;
    while (cin >> l >> r, l || r)
    {
        cout << dp(r) - dp(l - 1) << endl;
    }

    return 0;
}

1086. Hate 7 not to be a wife

single!

Still single!

GIGO is still single!

DS code Nong Jige is still single!

Therefore, he hates Valentine's day most in his life. Whether it's 214 or 77, he hates it!

GIGO observed 214 and 77 and found that:

2+1+4=7
7+7=7×2
77=7×11
Finally, he found that all this was related to 7 in the final analysis!

So now he even hates all the numbers related to 7!

What number is related to 7?

If an integer meets one of the following three conditions, we say that the integer is related to 7:

A bit in an integer is 7;
The sum of each bit of an integer is an integral multiple of 7;
This integer is an integral multiple of 7.
Now the problem comes: GIGO wants to know the sum of squares of integers unrelated to 7 in a certain interval.

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

typedef long long LL;

const int N = 20, P = 1e9 + 7;

struct F
{
    int s0, s1, s2;
}f[N][10][7][7];

int power7[N], power9[N];

int mod(LL x, int y)
{
    return (x % y + y) % y;
}

void init()
{
    for (int i = 0; i <= 9; i ++ )
    {
        if (i == 7) continue;
        auto& v = f[1][i][i % 7][i % 7];
        v.s0 ++, v.s1 += i, v.s2 += i * i;
    }

    LL power = 10;
    for (int i = 2; i < N; i ++, power *= 10)
        for (int j = 0; j <= 9; j ++ )
        {
            if (j == 7) continue;
            for (int a = 0; a < 7; a ++ )
                for (int b = 0; b < 7; b ++ )
                    for (int k = 0; k <= 9; k ++ )
                    {
                        if (k == 7) continue;
                        auto &v1 = f[i][j][a][b], &v2 = f[i - 1][k][mod(a - j * power, 7)][mod(b - j, 7)];
                        v1.s0 = mod(v1.s0 + v2.s0, P);
                        v1.s1 = mod(v1.s1 + v2.s1 + j * (power % P) % P * v2.s0, P);
                        v1.s2 = mod(v1.s2 + j * j * (power % P) % P * (power % P) % P * v2.s0 + v2.s2 + 2 * j * power % P * v2.s1, P);
                    }
        }

    power7[0] = 1;
    for (int i = 1; i < N; i ++ ) power7[i] = power7[i - 1] * 10 % 7;

    power9[0] = 1;
    for (int i = 1; i < N; i ++ ) power9[i] = power9[i - 1] * 10ll % P;
}

F get(int i, int j, int a, int b)
{
    int s0 = 0, s1 = 0, s2 = 0;
    for (int x = 0; x < 7; x ++ )
        for (int y = 0; y < 7; y ++ )
            if (x != a && y != b)
            {
                auto v = f[i][j][x][y];
                s0 = (s0 + v.s0) % P;
                s1 = (s1 + v.s1) % P;
                s2 = (s2 + v.s2) % P;
            }
    return {s0, s1, s2};
}

int dp(LL n)
{
    if (!n) return 0;

    LL backup_n = n % P;
    vector<int> nums;
    while (n) nums.push_back(n % 10), n /= 10;

    int res = 0;
    LL last_a = 0, last_b = 0;
    for (int i = nums.size() - 1; i >= 0; i -- )
    {
        int x = nums[i];
        for (int j = 0; j < x; j ++ )
        {
            if (j == 7) continue;
            int a = mod(-last_a * power7[i + 1], 7);
            int b = mod(-last_b, 7);
            auto v = get(i + 1, j, a, b);
            res = mod(
                res + 
                (last_a % P) * (last_a % P) % P * power9[i + 1] % P * power9[i + 1] % P * v.s0 % P + 
                v.s2 + 
                2 * last_a % P * power9[i + 1] % P * v.s1,
            P);
        }

        if (x == 7) break;
        last_a = last_a * 10 + x;
        last_b += x;

        if (!i && last_a % 7 && last_b % 7) res = (res + backup_n * backup_n) % P;
    }

    return res;
}

int main()
{
    int T;
    cin >> T;

    init();

    while (T -- )
    {
        LL l, r;
        cin >> l >> r;
        cout << mod(dp(r) - dp(l - 1), P) << endl;
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/127376/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.
#include<iostream>
#include<cstring>
using namespace std;

typedef long long ll;
const ll P=1e9+7;
int A[25];
ll pw[25];

struct node {ll cnt,sum,sum2;} f[20][7][7]; 

/*
f[I][sum][num]The status indicated is:
Starting from bit I, the sum (% 7) of each number from the highest bit to bit I is sum, and the whole number (% 7) is num
 For example, for the number 123 * * *, when I=3, sum=6, num=123

Note: f is stored when there is no upper bound
 Because there is no upper bound, that is, the remaining i bits can be filled in from 00... 00 ~ 99... 99, so no matter how many the number a [] is, it can be applied without resetting the f array every time

In this state, the
cnt Represents the number of numbers independent of 7
sum Represents the sum of all numbers unrelated to 7
sum2 Represents the sum of squares of all numbers unrelated to 7
*/

node dfs(int I,int sum,int num,bool lim){                       //Currently in bit I, the sum (% 7) of each number from the highest bit to bit I is sum, the whole number (% 7) is num, and lim indicates whether it fits the upper bound
    if (!I)  return (node){sum && num , 0 , 0};                 //The number has been filled in. According to the requirements of the topic, if sum and num are not 0 (cannot be divided by 7), it is a scheme
    if (!lim && f[I][sum][num].cnt>=0) return f[I][sum][num];  //Memorize. If you don't fit the upper bound (! lim), put back the recorded answers directly

    int up=lim ? A[I] : 9;                                     //The maximum number of digits I can be filled in
    node ans=(node){0,0,0};
    for (int i=0 ; i<=up ; i++)                                //Enumerating the number filled in bit I
    if (i!=7){
        node J=dfs(I-1,(sum+i)%7,(num*10+i)%7,lim && i==up);
        ll B=i*pw[I-1];                                        //B can be understood as the base value of the current layer. For example, if I=5, fill in 6, then B=60000
        (ans.cnt+=J.cnt)%=P;                                   //Count the occurrence times of numbers unrelated to 7
        (ans.sum+=J.cnt*B+J.sum)%=P;                          

        /*
        Count the sum of all independent numbers related to 7 (the sum of all independent numbers from the I-1st bit to the last bit has been calculated with dfs (I-1), I.e. J.sum, plus the I-th bit, I.e. J.cnt*B)
        For example, if I=5, the known irrelevant numbers are * * 61111, * * 62222, * * 63333 (random numbers)
        Then B=60000, J.sum=1111+2222+3333, J.cnt=3, ans.sum=61111+62222+63333
        */

        (ans.sum2+=J.cnt*B%P*B%P+J.sum2+2*J.sum%P*B%P)%=P;

        /*
        Count the sum of squares of all numbers independent of 7 from the ith to the last digit
        For example, if I=5, the known irrelevant numbers are * * 61111, * * 62222, * * 63333 (random numbers)
        For 61111 ^ 2 = (60000 + 1111) ^ 2 = (60000) ^ 2 + (1111) ^ 2 + 2 * 60000 * 1111
        62222,63333 Similarly
        Then ans.sum2=61111^2+62222^2+63333^2
                  =3*(60000)^2 + (1111^2+2222^2+3333^2) + 2*60000*(1111+2222+3333)
                  =J.cnt*B*B   + J.sum2                 + 2*B*J.sum
        It can be found that we can calculate the sum2 of the last I-bit by using the sum2 of the last I-1 bit
        */
    }
    if (!lim) f[I][sum][num]=ans;                             //Memorization: if it does not fit the upper bound (! lim), record it
    return ans;
}


ll solve (ll X){        //Decomposition digit
    int len=0;
    for ( ; X ; X/=10) A[++len]=X%10;
    return dfs(len,0,0,1).sum2;
}

int main(){
    int T;
    cin>>T,pw[0]=1,memset(f,-1,sizeof f);                       
    for(int i=1 ; i<21 ; i++) pw[i]=pw[i-1]*10%P;               //Power of pretreatment 10

    for (ll L,R ; T ; T--)
     scanf("%lld%lld",&L,&R),printf("%lld\n",(solve(R)-solve(L-1)+P)%P);
}


Author: Randolph
 Link: https://www.acwing.com/solution/content/57811/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Monotone queue optimization dp

135. Maximum suborder sum

Input an integer sequence with length n, and find a continuous subsequence with length no more than m, so that the sum of all numbers in the subsequence is the largest.

Note: the length of the subsequence is at least 1.
Let's focus on understanding how to monotone queues.

We find that if our right endpoint rr is fixed, our problem will change.

Find a left endpoint ll, which requires j ∈ [i − m,i − 1]j ∈ [i − m,i − 1]

This sentence means that the length of our interval can not exceed mm, and the interval length is at least 11. This is not nonsense

And sum[j]sum[j] should be as small as possible in order to maximize the interval sum, right.

So we find that the value of this jj is an interval, and most importantly, we just want the maximum value of this interval.

The interval maximum value can be processed through monotonic queue.

We find that if there is a position kk, this k < J < IK < J < I. and sum[k] ≥ sum[j]sum[k] ≥ sum[j]
In other words, a person learns before you, that is, he is older than you, and his strength is not as good as you. Can this person beat you?

Sorry, my strength doesn't allow me to beat you.

Let's analyze it rationally.

K < JK < J, that is to say, the length of the interval [k,i][k,i] must be greater than the length of the interval [j,i][j,i].

sum[k] ≥ sum[j]sum[k] ≥ sum[j], so sum[i] − sum[k] ≥ sum[i] − sum[j]sum[i] − sum[k] ≥ sum[i] − sum[j], that is, our [k,j] interval consumes more.

In that case, kk is really a dish, and it's really useless.

Our jj is not only closer to ii than kk, but also consumes less than kk.

So what reason do we have to choose kk.

Of course, we choose a machine that is new and consumes less. We certainly won't choose an old machine that consumes more.

Author: the lights on the Qinhuai River bank are dim
Link: https://www.acwing.com/solution/content/888/
Source: AcWing
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 300010, INF = 1e9;

int n, m;
int s[N];
int q[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &s[i]), s[i] += s[i - 1];

    int res = -INF;
    int hh = 0, tt = 0;

    for (int i = 1; i <= n; i ++ )
    {
        if (q[hh] < i - m) hh ++ ;
        res = max(res, s[i] - s[q[hh]]);
        while (hh <= tt && s[q[tt]] >= s[i]) tt -- ;
        q[ ++ tt] = i;
    }

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

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128103/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

1087. Mowing the lawn

After winning the best lawn competition in the town a year ago, FJ became lazy and never mowed the lawn again.

Now, a new round of the best lawn competition has begun again, and FJ hopes to win again.

However, FJ's lawn is very dirty, so FJ can only let his cows do the work.

FJ has N cows in a row, numbered 1 to N.

The efficiency of each cow is different, and the efficiency of cow i is Ei.

The cows with adjacent numbers are very familiar. If FJ arranges more than K cows with consecutive numbers, these cows will go on strike and have a party.

Therefore, FJ needs your help to find the most reasonable arrangement and calculate the maximum efficiency that FJ can get.

Note that the scheme shall not contain more than K cows with consecutive numbers.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 1e5 + 10;

int n, m;
LL s[N];
LL f[N];
int q[N];

LL g(int i)
{
    if (!i) return 0;
    return f[i - 1] - s[i];
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ )
    {
        scanf("%lld", &s[i]);
        s[i] += s[i - 1];
    }

    int hh = 0, tt = 0;
    for (int i = 1; i <= n; i ++ )
    {
        if (q[hh] < i - m) hh ++ ;
        f[i] = max(f[i - 1], g(q[hh]) + s[i]);
        while (hh <= tt && g(q[tt]) <= g(i)) tt -- ;
        q[ ++ tt] = i;
    }

    printf("%lld\n", f[n]);

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128401/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

1088. Travel issues

John is going to drive a car around a ring road.

There are a total of n stations on the highway. Each station has several liters of gasoline (some stations may have zero fuel). Each liter of fuel can drive a car for one kilometer.

John must start from a station, go all the stations clockwise (or counterclockwise) and return to the starting point.

At the beginning, the oil volume in the car was zero. John took all the oil at each station (the same is true at the starting station). There should be no oil during driving.

Task: judge whether each station can successfully travel around for a week according to conditions.
The first line is an integer n, which represents the number of stations on the ring road;

Next n lines, two integers PI and Di in each line, respectively represent the fuel storage of station i and the distance from station i to the next station in a clockwise direction.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 2e6 + 10;

int n;
int oil[N], dist[N];
LL s[N];
int q[N];
bool ans[N];

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ )
    {
        scanf("%d%d", &oil[i], &dist[i]);
        s[i] = s[i + n] = oil[i] - dist[i];
    }
    for (int i = 1; i <= n * 2; i ++ ) s[i] += s[i - 1];

    int hh = 0, tt = 0;
    q[0] = n * 2 + 1;
    for (int i = n * 2; i >= 0; i -- )
    {
        if (q[hh] > i + n) hh ++ ;
        if (i < n)
        {
            if (s[i] <= s[q[hh]]) ans[i + 1] = true;
        }
        while (hh <= tt && s[q[tt]] >= s[i]) tt -- ;
        q[ ++ tt] = i;
    }

    dist[0] = dist[n];
    for (int i = 1; i <= n; i ++ ) s[i] = s[i + n] = oil[i] - dist[i - 1];
    for (int i = 1; i <= n * 2; i ++ ) s[i] += s[i - 1];

    hh = 0, tt = 0;
    q[0] = 0;
    for (int i = 1; i <= n * 2; i ++ )
    {
        if (q[hh] < i - n) hh ++ ;
        if (i > n)
        {
            if (s[i] >= s[q[hh]]) ans[i - n] = true;
        }
        while (hh <= tt && s[q[tt]] <= s[i]) tt -- ;
        q[ ++ tt] = i;
    }

    for (int i = 1; i <= n; i ++ )
        if (ans[i]) puts("TAK");
        else puts("NIE");

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128104/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

1089. Beacon fire transmission

Beacon towers are important military defense facilities, which are generally built in important traffic roads or dangerous places.

In case of military intelligence, smoke is used during the day and fire is used at night to transmit military intelligence.

There are n beacon towers between two cities. Each beacon tower sends a signal at a certain price.

In order to transmit information accurately, at least one of the m consecutive beacon towers must send a signal.

Now enter n,m and the cost of each beacon tower. Please calculate the minimum total cost of accurately transmitting information between the two cities.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 2e5 + 10, INF = 1e9;

int n, m;
int w[N], q[N];
int f[N];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);

    int hh = 0, tt = 0;
    for (int i = 1; i <= n; i ++ )
    {
        if (q[hh] < i - m) hh ++ ;
        f[i] = f[q[hh]] + w[i];
        while (hh <= tt && f[q[tt]] >= f[i]) tt -- ;
        q[ ++ tt] = i;
    }

    int res = INF;
    for (int i = n - m + 1; i <= n; i ++ ) res = min(res, f[i]);

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

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128105/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

1090. Green channel

There are a total of n questions to copy in the green passage of senior two mathematics. The numbers are 1,2,..., n. It takes ai minutes to copy the i question.

Little Y decided to copy this in no more than t minutes, so there must be an empty question.

Each question is either not written or copied, not half written.

Some empty questions with continuous subscripts are called an empty question segment, and its length is the number of questions contained.

This will naturally cause Mr. Ma's anger. The longer the longest empty paragraph, the more angry Mr. Ma is.

Now, little Y wants to know what questions he will write in this t minute, so as to minimize Mr. Ma's anger.

Because Xiao Y is very smart, you just tell him how long the longest empty paragraph is at least, and there is no need to output the scheme.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 50010, INF = 1e9;

int n, m;
int w[N];
int f[N], q[N];

bool check(int k)
{
    f[0] = 0;
    int hh = 0, tt = 0;
    for (int i = 1; i <= n; i ++ )
    {
        if (hh <= tt && q[hh] < i - k - 1) hh ++ ;
        f[i] = f[q[hh]] + w[i];
        while (hh <= tt && f[q[tt]] >= f[i]) tt -- ;
        q[ ++ tt] = i;
    }

    int res = INF;
    for (int i = n - k; i <= n; i ++ ) res = min(res, f[i]);

    return res <= m;
}

int main()
{
    scanf("%d%d", &n, &m);

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

    int l = 0, r = n;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }

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

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128106/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

1091. Ideal square (binary monotone queue optimization

There is an a × b is a matrix composed of integers. Now please find an n from it × n, so that the difference between the maximum value and the minimum value in all numbers in the region is the smallest.

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010, INF = 1e9;

int n, m, k;
int w[N][N];
int row_min[N][N], row_max[N][N];
int q[N];

void get_min(int a[], int b[], int tot)
{
    int hh = 0, tt = -1;
    for (int i = 1; i <= tot; i ++ )
    {
        if (hh <= tt && q[hh] <= i - k) hh ++ ;
        while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
        q[ ++ tt] = i;
        b[i] = a[q[hh]];
    }
}

void get_max(int a[], int b[], int tot)
{
    int hh = 0, tt = -1;
    for (int i = 1; i <= tot; i ++ )
    {
        if (hh <= tt && q[hh] <= i - k) hh ++ ;
        while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
        q[ ++ tt] = i;
        b[i] = a[q[hh]];
    }
}



int main()
{
    scanf("%d%d%d", &n, &m, &k);

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

    for (int i = 1; i <= n; i ++ )
    {
        get_min(w[i], row_min[i], m);
        get_max(w[i], row_max[i], m);
    }

    int res = INF;
    int a[N], b[N], c[N];
    for (int i = k; i <= m; i ++ )
    {
        for (int j = 1; j <= n; j ++ ) a[j] = row_min[j][i];
        get_min(a, b, n);

        for (int j = 1; j <= n; j ++ ) a[j] = row_max[j][i];
        get_max(a, c, n);

        for (int j = k; j <= n; j ++ ) res = min(res, c[j] - b[j]);
    }

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

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128412/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Slope optimization dp

300. Organization of the mandate 1

There are N tasks in a sequence waiting to be executed on one machine, and their sequence shall not be changed.

The machine will divide the N tasks into several batches, and each batch contains several consecutive tasks.

From time 0, the task is processed in batches, and the time required to execute the ith task is Ti.

In addition, before each batch of tasks starts, the machine needs the start-up time of S, so the time required to execute a batch of tasks is the sum of the start-up time s and the time required for each task.

After a task is executed, it will wait in the machine until the batch of tasks are executed completely.

In other words, the same batch of tasks will be completed at the same time.

The cost of each task is its completion time multiplied by a cost coefficient Ci.

Please plan a grouping scheme for the machine to minimize the total cost.
1≤N≤5000,
0≤S≤50,
1≤Ti,Ci≤100

analysis
Why should we enumerate each group? To get the number of times to start the machine and then calculate the cost
We can find that as long as we are divided into groups, the machines that have not been grouped in the back will increase the corresponding expenses. Fortunately, we can calculate the increased expenses now, so we only need to add the extra expenses in advance
State transition equation: F [i] = min (f [J] + (C [i] − C [J]) × t[i]+(c[n]−c[j]) × s)f[i]=min(f[j]+(c[i]−c[j]) × t[i]+(c[n]−c[j]) × s),0≤j<i0≤j<i
Ibid., c[i]c[i] and t[i]t[i] are prefixes and.

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5010;
int t[N],c[N];
int f[N];
int n,s;
int main()
{
    cin>>n>>s;
    for(int i=1;i<=n;i++)
    {
        cin>>t[i]>>c[i];
        t[i]+=t[i-1];
        c[i]+=c[i-1];
    }
    memset(f,0x3f3f3f3f,sizeof f);
    f[0]=0;
    for(int i=1;i<=n;i++)
        for(int j=0;j<i;j++)    
            f[i]=min(f[i],f[j]+(c[i]-c[j])*t[i]+(c[n]-c[j])*s);
    cout<<f[n]<<endl;
    return 0;
}

Author: Fighting_Peter
 Link: https://www.acwing.com/solution/content/13036/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

1≤N≤3×105,
1≤Ti,Ci≤512,
0≤S≤512

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 300010;

int n, s;
LL c[N], t[N];
LL f[N];
int q[N];

int main()
{
    scanf("%d%d", &n, &s);
    for (int i = 1; i <= n; i ++ )
    {
        scanf("%lld%lld", &t[i], &c[i]);
        t[i] += t[i - 1];
        c[i] += c[i - 1];
    }

    int hh = 0, tt = 0;
    q[0] = 0;

    for (int i = 1; i <= n; i ++ )
    {
        while (hh < tt && (f[q[hh + 1]] - f[q[hh]]) <= (t[i] + s) * (c[q[hh + 1]] - c[q[hh]])) hh ++ ;
        int j = q[hh];
        f[i] = f[j] - (t[i] + s) * c[j] + t[i] * c[i] + s * c[n];
        while (hh < tt && (__int128)(f[q[tt]] - f[q[tt - 1]]) * (c[i] - c[q[tt - 1]]) >= (__int128)(f[i] - f[q[tt - 1]]) * (c[q[tt]] - c[q[tt - 1]])) tt -- ;
        q[ ++ tt] = i;
    }

    printf("%lld\n", f[n]);

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128994/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

302. Organization of the mandate 3

1≤N≤3×105,
0≤S,Ci≤512,
−512≤Ti≤512

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 300010;

int n, s;
LL t[N], c[N];
LL f[N];
int q[N];

int main()
{
    scanf("%d%d", &n, &s);
    for (int i = 1; i <= n; i ++ )
    {
        scanf("%lld%lld", &t[i], &c[i]);
        t[i] += t[i - 1];
        c[i] += c[i - 1];
    }

    int hh = 0, tt = 0;
    q[0] = 0;

    for (int i = 1; i <= n; i ++ )
    {
        int l = hh, r = tt;
        while (l < r)
        {
            int mid = l + r >> 1;
            if (f[q[mid + 1]] - f[q[mid]] > (t[i] + s) * (c[q[mid + 1]] - c[q[mid]])) r = mid;
            else l = mid + 1;
        }

        int j = q[r];
        f[i] = f[j] -   (t[i] + s) * c[j] + t[i] * c[i] + s * c[n];
        while (hh < tt && (double)(f[q[tt]] - f[q[tt - 1]]) * (c[i] - c[q[tt - 1]]) >= (double)(f[i] - f[q[tt - 1]]) * (c[q[tt]] - c[q[tt - 1]])) tt -- ;
        q[ ++ tt] = i;
    }

    printf("%lld\n", f[n]);

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/128996/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.
yes NN There are tasks waiting to be completed (the order does not change), which NN A task is divided into several batches, each batch contains several adjacent tasks. From time 00, these tasks are processed in batches, and the second batch ii How long does it take to complete a task alone TiTi . There is only one machine, and the machine needs to start up before each batch of tasks starts SS,The time required to complete this batch of tasks is the sum of the time required for each task (the same batch of tasks will be completed at the same time). The cost of each task is its completion time multiplied by its cost coefficient CiCi. Please determine a grouping scheme to minimize the total cost.

T1
1⩽N⩽5000,0⩽S⩽50,1⩽Ti,Ci⩽1001⩽N⩽5000,0⩽S⩽50,1⩽Ti,Ci⩽100
 order sumT[i]=∑ij=1T[j],sumC[i]=∑ij=1F[j]sumT[i]=∑j=1iT[j],sumC[i]=∑j=1iF[j],that
f[p][i]=min(f[p−1][j]+(sumT[i]+p×S)×(sumC[i]−sumC[j]))
f[p][i]=min(f[p−1][j]+(sumT[i]+p×S)×(sumC[i]−sumC[j]))

Consider the cost calculation in advance. Each time a batch of tasks are assigned, the time of each subsequent task will be affected SS The contribution can be calculated in advance.
f[i]=min(f[j]+sumT[i]×(sumC[i]−sumC[j])+S×(sumC[n]−sumC[j]))
f[i]=min(f[j]+sumT[i]×(sumC[i]−sumC[j])+S×(sumC[n]−sumC[j]))
code

#include <bits/stdc++.h>
using namespace std;
const int N=5010;
int n,s,t[N],c[N],f[N];

int main() 
{
    scanf( "%d%d",&n,&s );
    for ( int i=1; i<=n; i++ )
        scanf( "%d%d",t+i,c+i );

    memset( f,0x3f,sizeof f );
    f[0]=0;
    for ( int i=1; i<=n; i++ )
        t[i]+=t[i-1],c[i]+=c[i-1];
    for ( int i=1; i<=n; i++ )
     for ( int j=0; j<i; j++ )
        f[i]=min( f[i],f[j]+(c[i]-c[j])*t[i]+s*(c[n]-c[j]) );

    printf( "%d\n",f[n] );
} 
T2
1≤N≤3e51≤N≤3e5 1≤Ti,Ci≤512,0≤S≤5121≤Ti,Ci≤512,0≤S≤512
NN It becomes larger and needs to be added with slope optimization.
f[i]=min(f[j]+sumT[i]×(sumC[i]−sumC[j])+S×(sumC[n]−sumC[j]))
f[i]=min(f[j]+sumT[i]×(sumC[i]−sumC[j])+S×(sumC[n]−sumC[j]))

Consider transforming it into a slope equation.
f[j]=(sumT[i]+S)×sumC[j]+f[i]−sumC[i]×sumT[i]−sumC[n]×S
f[j]=(sumT[i]+S)×sumC[j]+f[i]−sumC[i]×sumT[i]−sumC[n]×S
 code
#include <bits/stdc++.h>
#define ll long long
#define lb long double
using namespace std;
const int N=3e5+10;
int n,s,q[N],h=0,t=0;
ll sc[N],st[N],f[N];

lb slope( int x,int y ) { return (lb)(f[y]-f[x])/(sc[y]-sc[x]); }

int main()
{
    scanf( "%d%d",&n,&s );
    for ( int i=1; i<=n; i++ )
    {
        scanf( "%lld%lld",&st[i],&sc[i] );
        st[i]+=st[i-1]; sc[i]+=sc[i-1];
    }

    for ( int i=1; i<=n; i++ )
    {
        while ( h<t && slope(q[h],q[h+1])<=( st[i]+s ) ) h++;
        f[i]=f[q[h]]-( st[i]+s )*sc[q[h]]+sc[i]*st[i]+s*sc[n];
        while ( h<t && slope(q[t-1],q[t])>=slope(q[t],i) ) t--;
        q[++t]=i;
    }

    printf( "%lld",f[n] );
}
T3
1≤N≤3e5,0≤S,Ci≤512,|Ti|≤5121≤N≤3e5,0≤S,Ci≤512,|Ti|≤512

Task execution time tt It may be negative, so the slope is not monotonic,
You can't just keep more than S+sumT[i]S+sumT[i] The entire convex shell should be maintained
 At this time, the team leader is not necessarily the optimal decision. It is necessary to find a position by binary search,
Make the slope on the left less than S+sumT[i]S+sumT[i] ,Right slope greater than S+sumT[i]S+sumT[i]

Note: this question AcWing The data is strong, so it is recommended to slope To cross multiply, you need to use __int128 perhaps double .

code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10;
int n,s,q[N],h=0,t=0;
ll sc[N],st[N];
double f[N];

int main()
{
    scanf( "%d%d",&n,&s );
    for ( int i=1; i<=n; i++ )
    {
        scanf( "%lld%lld",&st[i],&sc[i] );
        st[i]+=st[i-1]; sc[i]+=sc[i-1];
    }

    for ( int i=1; i<=n; i++ )
    {
        int l=h,r=t;
        while ( l<r )
        {
            int mid=(l+r)/2;
            if ( (f[q[mid+1]]-f[q[mid]])>(st[i]+s)*(sc[q[mid+1]]-sc[q[mid]]) ) r=mid;
            else l=mid+1;
        }
        f[i]=f[q[l]]-( st[i]+s )*sc[q[l]]+sc[i]*st[i]+s*sc[n];
        while ( h<t && ( f[q[t]]-f[q[t-1]] )*( sc[i]-sc[q[t]] )>=( f[i]-f[q[t]] )*( sc[q[t]]-sc[q[t-1]]  ) ) t--;
        q[++t]=i;
    }

    printf( "%.0lf",f[n] );
}

Author: RingweEH
 Link: https://www.acwing.com/solution/content/23573/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

303. Transport kittens

Small S is a farmer. He keeps M cats and employs P keepers.

There is a straight road in the farm. There are N mountains on the side of the road, numbered from 1 to N.

The distance between mountain i and mountain i − 1 is Di.

The breeders live on mountain 1.

One day, the cat went out to play.

The i-th cat went to Hi mountain to play until Ti stopped, and then waited in place for the keeper to pick it up.

Breeders must recycle all cats.

Each breeder walked along the road from mountain 1 to mountain N and picked up all the cats waiting on each mountain.

It takes time for the breeder to walk on the road, and the speed is 1m / unit time.

The time for breeders to pick up cats on each mountain can be ignored, and the number of cats they can carry is infinite.

For example, there are two mountains 1 apart. A cat plays on mountain 2 and waits until time 3.

If the keeper starts from mountain 1 at time 2 or 3, he can receive the cat. The waiting time of the cat is 0 or 1.

If he starts at time 1, he will pass mountain 2 at time 2 and can't receive the cat still playing at that time.

Your task is to plan the departure time of each breeder from mountain 1 so that the total waiting time of all cats is as small as possible.

The breeder's departure time can be negative.
t[i] represents the playing time of the ith kitten, and d[i] represents the distance from the ith kitten to the starting point
Let a[i] = t[i] - d[i]
Sort by a[i]
f[i][j] means the first I breeders, and the last kitten is j
s denotes the prefix and of a
f[i][j] = f[i - 1][k] + aj - (s[j] - s[k]);
transposition
f[i - 1][k] + s[k] = a[j]k + f[i][j] - a[j]*j + s[j]
Because the slope increases only and k increases only, the monotone queue is used to maintain the convex hull, and find the point where the first slope is greater than the slope, and then transfer

Or to find out what the meaning of variables is, LL open the whole
The first step of transformation is still magical. I'll give you a lot of things to find out what's really useful
What's useful for each cat is the time when they can start to pick up. The distance and time can be directly transformed together

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long LL;
const int N = 1e5 + 5,M = N,P = 110;

int d[N],n,m,p,q[N];
LL a[N],s[N],f[P][N];

LL get_y(int i,int j)
{
    return f[i - 1][j] + s[j];
}

int main()
{
    cin >> n >> m >> p;
    for(int i = 2;i <= n;i ++)
        scanf("%d",&d[i]),d[i] += d[i - 1];

    for(int i = 1;i <= m;i ++)
    {
        int hi,ti;
        scanf("%d%d",&hi,&ti);
        a[i] = ti - d[hi];
    }

    sort(a + 1,a + 1 + m);
    for(int i = 1;i <= m;i ++)
        s[i] = s[i - 1] + a[i];

    memset(f,0x3f,sizeof f);
    for(int i = 0;i <= p;i ++)
        f[i][0] = 0;

    for(int i = 1;i <= p;i ++)
    {
        int tt = 0,hh = 0;
        for(int j = 1;j <= m;j ++)
        {
            while(tt > hh && get_y(i,q[hh + 1]) - get_y(i,q[hh]) <= a[j] * (q[hh + 1] - q[hh]))hh ++;
            int k = q[hh];
            f[i][j] = f[i - 1][k] + (j - k) * a[j] - (s[j] - s[k]);
            while(tt > hh && (get_y(i,q[tt]) - get_y(i,q[tt - 1])) * (j - q[tt])>= (get_y(i,j) - get_y(i,q[tt])) * (q[tt] - q[tt - 1]))tt --;
            q[++ tt] = j;
        }
    }

    cout << f[p][m];
}

Author: Yu Sheng
 Link: https://www.acwing.com/solution/content/5371/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Segment tree

245. Can you answer these questions

Given A sequence A of length N and M instructions, each instruction may be one of the following two:

1 x y, the maximum continuous sub segment sum in the query interval [x,y], i.e. maxx ≤ l ≤ r ≤ y {∑ i=lrA[i]}.
2 x y, change A[x] to y.
For each query instruction, an integer is output to represent the answer.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 500010;

int n, m;
int w[N];
struct Node
{
    int l, r;
    int sum, lmax, rmax, tmax;
}tr[N * 4];

void pushup(Node &u, Node &l, Node &r)
{
    u.sum = l.sum + r.sum;
    u.lmax = max(l.lmax, l.sum + r.lmax);
    u.rmax = max(r.rmax, r.sum + l.rmax);
    u.tmax = max(max(l.tmax, r.tmax), l.rmax + r.lmax);
}

void pushup(int u)
{
    pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}

void build(int u, int l, int r)
{
    if (l == r) tr[u] = {l, r, w[r], w[r], w[r], w[r]};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u, int x, int v)
{
    if (tr[u].l == x && tr[u].r == x) tr[u] = {x, x, v, v, v, v};
    else
    {
        int mid = tr[u].l + tr[u].r >> 1;
        if (x <= mid) modify(u << 1, x, v);
        else modify(u << 1 | 1, x, v);
        pushup(u);
    }
}

Node query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u];
    else
    {
        int mid = tr[u].l + tr[u].r >> 1;
        if (r <= mid) return query(u << 1, l, r);
        else if (l > mid) return query(u << 1 | 1, l, r);
        else
        {
            auto left = query(u << 1, l, r);
            auto right = query(u << 1 | 1, l, r);
            Node res;
            pushup(res, left, right);
            return res;
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
    build(1, 1, n);

    int k, x, y;
    while (m -- )
    {
        scanf("%d%d%d", &k, &x, &y);
        if (k == 1)
        {
            if (x > y) swap(x, y);
            printf("%d\n", query(1, x, y).tmax);
        }
        else modify(1, x, y);
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/167568/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

246. Interval maximum common divisor

Given A sequence A with length N and M instructions, each instruction may be one of the following two:

C l r d means adding d to A[l],A[l+1],..., A[r].
Q l r, represents the maximum common divisor (GCD) of query A[l],A[l+1],..., A[r].
For each query, an integer is output to represent the answer.

#include<bits/stdc++.h>
#define node Node
using namespace std;
typedef long long LL;
#define int long long
const int N = 500010;
int n,m,w[N];
struct node{
    int l,r,sum,d;
}tr[N*4];

int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}

void pushup(node & t,node & a,node &b){
    t.sum=a.sum+b.sum;
    t.d=gcd(a.d,b.d);
}
void pushup(int u){
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}

void build(int u, int l, int r)
{
    if (l == r)
    {
        LL b = w[r] - w[r - 1];
        tr[u] = {l, r, b, b};
    }
    else
    {
        tr[u].l = l, tr[u].r = r;
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u,int x,int v){
    if(tr[u].l==x&&tr[u].r==x){
         tr[u].sum+=v;
         tr[u].d+=v;
    }
    else{
        
        int mid= tr[u].l+tr[u].r>>1;
        if(mid<x)modify(u<<1|1,x,v);
        else modify(u<<1,x,v);
        
        pushup(u);
    }
}

Node query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u];
    else
    {
        int mid = tr[u].l + tr[u].r >> 1;
        if (r <= mid) return query(u << 1, l, r);//mid is on the right of R. go to the left to find the answer
        //(all boundary judgments recursive to the left use the equal sign
        
        else if (l > mid) return query(u << 1 | 1, l, r);//mid is on the left of L. go to the right to find the answer
        
        else//If mid is between L and R, you can find the answer recursively on both sides
        {
            auto left = query(u << 1, l, r);
            auto right = query(u << 1 | 1, l, r);
            Node res;
            pushup(res, left, right);
            return res;
        }
    }
}



signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>w[i];
    build(1,1,n);
    while(m--){
        char c;
        int l,r;
        cin>>c>>l>>r;
        if(c=='C'){
            int v;
            cin>>v;
            modify(1,l,v);
            //The difference idea is that adding a number to the interval l~r should be added to l and subtracted from r+1
            if(r+1<=n)modify(1,r+1,-v);//boundary
        }
        else{
            node left=query(1,1,l);
            node right={0,0,0,0};
            if(l+1<=r)right=query(1,l+1,r);
            cout<<abs( gcd(left.sum ,  right.d )  )<<endl;
            
        }
    }
}

243. A simple integer problem 2

Given A sequence A with length N and M instructions, each instruction may be one of the following two:

C l r d means adding d to A[l],A[l+1],..., A[r].
Q l r, represents the sum of the l ∼ r numbers in the query sequence.
For each query, an integer is output to represent the answer.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 100010;

int n, m;
int w[N];
struct Node
{
    int l, r;
    LL sum, add;
}tr[N * 4];

void pushup(int u)
{
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}

void pushdown(int u)
{
    auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
    if (root.add)
    {
        left.add += root.add, left.sum += (LL)(left.r - left.l + 1) * root.add;
        right.add += root.add, right.sum += (LL)(right.r - right.l + 1) * root.add;
        root.add = 0;
    }
}

void build(int u, int l, int r)
{
    if (l == r) tr[u] = {l, r, w[r], 0};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u, int l, int r, int d)
{
    if (tr[u].l >= l && tr[u].r <= r)
    {
        tr[u].sum += (LL)(tr[u].r - tr[u].l + 1) * d;
        tr[u].add += d;
    }
    else    // We must split
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, d);
        if (r > mid) modify(u << 1 | 1, l, r, d);
        pushup(u);
    }
}

LL query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum;

    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    LL sum = 0;
    if (l <= mid) sum = query(u << 1, l, r);
    if (r > mid) sum += query(u << 1 | 1, l, r);
    return sum;
}


int main()
{
    scanf("%d%d", &n, &m);

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

    build(1, 1, n);

    char op[2];
    int l, r, d;

    while (m -- )
    {
        scanf("%s%d%d", op, &l, &r);
        if (*op == 'C')
        {
            scanf("%d", &d);
            modify(1, l, r, d);
        }
        else printf("%lld\n", query(1, l, r));
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/167900/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

1277. Maintenance sequence

The teacher gave Xiaoke a task to maintain the sequence. Now Xiaoke wants you to help him finish it.

If you have a sequence with length N, you might as well set it as a1,a2,..., aN.

There are three types of operation:

Multiply all the numbers in the sequence by one value;
Add a value to all the numbers in the sequence;
Ask the sum of a number in the sequence. Since the answer may be large, you only need to output the value of the digital analog P

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 100010;

int n, p, m;
int w[N];
struct Node
{
    int l, r;
    int sum, add, mul;
}tr[N * 4];

void pushup(int u)
{
    tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % p;
}

void eval(Node &t, int add, int mul)
{
    t.sum = ((LL)t.sum * mul + (LL)(t.r - t.l + 1) * add) % p;
    t.mul = (LL)t.mul * mul % p;
    t.add = ((LL)t.add * mul + add) % p;
}

void pushdown(int u)
{
    eval(tr[u << 1], tr[u].add, tr[u].mul);
    eval(tr[u << 1 | 1], tr[u].add, tr[u].mul);
    tr[u].add = 0, tr[u].mul = 1;
}

void build(int u, int l, int r)
{
    if (l == r) tr[u] = {l, r, w[r], 0, 1};
    else
    {
        tr[u] = {l, r, 0, 0, 1};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u, int l, int r, int add, int mul)
{
    if (tr[u].l >= l && tr[u].r <= r) eval(tr[u], add, mul);
    else
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, add, mul);
        if (r > mid) modify(u << 1 | 1, l, r, add, mul);
        pushup(u);
    }
}

int query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum;

    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    int sum = 0;
    if (l <= mid) sum = query(u << 1, l, r);
    if (r > mid) sum = (sum + query(u << 1 | 1, l, r)) % p;
    return sum;
}

int main()
{
    scanf("%d%d", &n, &p);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
    build(1, 1, n);

    scanf("%d", &m);
    while (m -- )
    {
        int t, l, r, d;
        scanf("%d%d%d", &t, &l, &r);
        if (t == 1)
        {
            scanf("%d", &d);
            modify(1, l, r, 0, d);
        }
        else if (t == 2)
        {
            scanf("%d", &d);
            modify(1, l, r, d, 1);
        }
        else printf("%d\n", query(1, l, r));
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/167944/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

3301. Star Trek

Jody wants to plan an interstellar journey. Interstellar space can be regarded as a three-dimensional coordinate system. Jody has n(n ≤ 109) power units arranged in a row (subscript from 1 to n).

The ith power unit can increase the coordinates of his spacecraft in three dimensions by Xi, Yi and Zi respectively.

Initially, all parameters of these power units were 0.

During the planning process, Jody may adjust the power plant or evaluate the power of some power plants.

Specifically, Jody will perform m(m ≤ 40000) operations. Each operation may be one of the following four operations:

Power increase: specify an interval [L,R] and three parameters a, B and C to increase the three-dimensional coordinates of all power units in the interval by a, B and C respectively
Power enhancement: specify an interval [L,R] and a parameter k to multiply the three-dimensional coordinates of all power units in the interval by k
Power steering: specify an interval [L,R] to change the x, y and z coordinates of all power units in the interval into the original y, z and x coordinates respectively
Power query: specify an interval [L,R] and ask how far Jody can be sent to the starting point if all power units in the interval are used at one time (the square of the output distance divided by the remainder of 109 + 7)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

typedef long long LL;
const int N = 80010, MOD = 1e9 + 7;

int n, m;
struct Q
{
    int t, l, r, k, a, b, c;
}q[N];
vector<int> xs;
struct Node
{
    int l, r, k;
    int a[3], b[3], s[3];

    int get_len()
    {
        return xs[r] - xs[l - 1];
    }
}tr[N * 4];

int get(int x)
{
    return lower_bound(xs.begin(), xs.end(), x) - xs.begin();
}

void pushup(int u)
{
    auto l = tr[u << 1].s, r = tr[u << 1 | 1].s;
    for (int i = 0; i < 3; i ++ )
        tr[u].s[i] = (l[i] + r[i]) % MOD;
}

void rotate(int a[])
{
    int t = a[0];
    a[0] = a[1], a[1] = a[2], a[2] = t;
}

void eval(int u, int k)
{
    k %= 3;
    for (int i = 0; i < k; i ++ )
    {
        rotate(tr[u].a), rotate(tr[u].b), rotate(tr[u].s);
    }
    tr[u].k += k;
}

void eval(int u, int a[], int b[])
{
    for (int i = 0; i < 3; i ++ )
    {
        tr[u].s[i] = ((LL)tr[u].s[i] * a[i] + (LL)tr[u].get_len() * b[i]) % MOD;
        int c = (LL)tr[u].a[i] * a[i] % MOD;
        int d = ((LL)tr[u].b[i] * a[i] + b[i]) % MOD;
        tr[u].a[i] = c, tr[u].b[i] = d;
    }
}

void pushdown(int u)
{
    eval(u << 1, tr[u].k), eval(u << 1 | 1, tr[u].k);
    tr[u].k = 0;

    eval(u << 1, tr[u].a, tr[u].b), eval(u << 1 | 1, tr[u].a, tr[u].b);
    for (int i = 0; i < 3; i ++ )
        tr[u].a[i] = 1, tr[u].b[i] = 0;
}

void build(int u, int l, int r)
{
    tr[u] = {l, r};
    for (int i = 0; i < 3; i ++ ) tr[i].a[i] = 1;
    if (l == r) return;
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}

void update(int u, int l, int r, int k, int a[], int b[])
{
    if (tr[u].l >= l && tr[u].r <= r) eval(u, k), eval(u, a, b);
    else
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) update(u << 1, l, r, k, a, b);
        if (r > mid) update(u << 1 | 1, l, r, k, a, b);
        pushup(u);
    }
}

vector<int> query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r) return {tr[u].s[0], tr[u].s[1], tr[u].s[2]};
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    vector<int> res(3);
    if (l <= mid) res = query(u << 1, l, r);
    if (r > mid)
    {
        auto t = query(u << 1 | 1, l, r);
        for (int i = 0; i < 3; i ++ )
            res[i] = (res[i] + t[i]) % MOD;
    }
    return res;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i ++ )
    {
        q[i].k = 1;
        scanf("%d%d%d", &q[i].t, &q[i].l, &q[i].r);
        if (q[i].t == 1) scanf("%d%d%d", &q[i].a, &q[i].b, &q[i].c);
        else if (q[i].t == 2) scanf("%d", &q[i].k);
        xs.push_back(q[i].l - 1), xs.push_back(q[i].r);
    }
    sort(xs.begin(), xs.end());
    xs.erase(unique(xs.begin(), xs.end()), xs.end());

    build(1, 0, xs.size() - 1);
    for (int i = 0; i < m; i ++ )
    {
        int t = q[i].t, l = get(q[i].l - 1) + 1, r = get(q[i].r);
        int a[] = {q[i].k, q[i].k, q[i].k}, b[] = {q[i].a, q[i].b, q[i].c};
        if (t == 1 || t == 2)
            update(1, l, r, 0, a, b);
        else if (t == 3)
            update(1, l, r, 1, a, b);
        else
        {
            auto t = query(1, l, r);
            LL sum = 0;
            for (int j = 0; j < 3; j ++ )
                sum += (LL)t[j] * t[j];
            printf("%lld\n", sum % MOD);
        }
    }
    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/987439/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

247. Atlantis (scanline method)

The input contains multiple sets of test cases.

For each set of test cases, the first line contains the integer n, representing the total number of maps.

Next, n lines depict each map. Each line contains four numbers x1,y1,x2,y2 (not necessarily integers), (x1,y1) and (x2,y2) are the upper left corner and lower right corner of the map respectively.

Notice that the x axis extends from top to bottom and the y axis extends from left to right.

When the input case n=0, it means that the input is terminated and the case does not need to be processed.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 100010;

int n;
struct Segment
{
    double x, y1, y2;
    int k;
    bool operator< (const Segment &t)const
    {
        return x < t.x;
    }
}seg[N * 2];
struct Node
{
    int l, r;
    int cnt;
    double len;
}tr[N * 8];

vector<double> ys;

int find(double y)
{
    return lower_bound(ys.begin(), ys.end(), y) - ys.begin();
}

void pushup(int u)
{
    if (tr[u].cnt) tr[u].len = ys[tr[u].r + 1] - ys[tr[u].l];
    else if (tr[u].l != tr[u].r)
    {
        tr[u].len = tr[u << 1].len + tr[u << 1 | 1].len;
    }
    else tr[u].len = 0;
}

void build(int u, int l, int r)
{
    tr[u] = {l, r, 0, 0};
    if (l != r)
    {
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    }
}

void modify(int u, int l, int r, int k)
{
    if (tr[u].l >= l && tr[u].r <= r)
    {
        tr[u].cnt += k;
        pushup(u);
    }
    else
    {
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, k);
        if (r > mid) modify(u << 1 | 1, l, r, k);
        pushup(u);
    }
}

int main()
{
    int T = 1;
    while (scanf("%d", &n), n)
    {
        ys.clear();
        for (int i = 0, j = 0; i < n; i ++ )
        {
            double x1, y1, x2, y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            seg[j ++ ] = {x1, y1, y2, 1};
            seg[j ++ ] = {x2, y1, y2, -1};
            ys.push_back(y1), ys.push_back(y2);
        }

        sort(ys.begin(), ys.end());
        ys.erase(unique(ys.begin(), ys.end()), ys.end());

        build(1, 0, ys.size() - 2);

        sort(seg, seg + n * 2);

        double res = 0;
        for (int i = 0; i < n * 2; i ++ )
        {
            if (i > 0) res += tr[1].len * (seg[i].x - seg[i - 1].x);
            modify(1, find(seg[i].y1), find(seg[i].y2) - 1, seg[i].k);
        }

        printf("Test case #%d\n", T ++ );
        printf("Total explored area: %.2lf\n\n", res);
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/167934/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Chairman tree

256. Maximum XOR and

Given a sequence of nonnegative integers a, the initial length is N.

There are M operations. There are two types of operations:

A x: add operation, which means that a number x is added at the end of the sequence, and the length N of the sequence is increased by 1.
Q l r x: query operation, you need to find a position p, which satisfies l ≤ p ≤ r, so that: a[p] xor a[p+1] xor... xor a[N] xor x is the maximum, and this maximum value is output.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 600010, M = N * 25;

int n, m;
int s[N];
int tr[M][2], max_id[M];
int root[N], idx;

void insert(int i, int k, int p, int q)
{
    if (k < 0)
    {
        max_id[q] = i;
        return;
    }
    int v = s[i] >> k & 1;
    if (p) tr[q][v ^ 1] = tr[p][v ^ 1];
    tr[q][v] = ++ idx;
    insert(i, k - 1, tr[p][v], tr[q][v]);
    max_id[q] = max(max_id[tr[q][0]], max_id[tr[q][1]]);
}

int query(int root, int C, int L)
{
    int p = root;
    for (int i = 23; i >= 0; i -- )
    {
        int v = C >> i & 1;
        if (max_id[tr[p][v ^ 1]] >= L) p = tr[p][v ^ 1];
        else p = tr[p][v];
    }

    return C ^ s[max_id[p]];
}

int main()
{
    scanf("%d%d", &n, &m);

    max_id[0] = -1;
    root[0] = ++ idx;
    insert(0, 23, 0, root[0]);

    for (int i = 1; i <= n; i ++ )
    {
        int x;
        scanf("%d", &x);
        s[i] = s[i - 1] ^ x;
        root[i] = ++ idx;
        insert(i, 23, root[i - 1], root[i]);
    }

    char op[2];
    int l, r, x;
    while (m -- )
    {
        scanf("%s", op);
        if (*op == 'A')
        {
            scanf("%d", &x);
            n ++ ;
            s[n] = s[n - 1] ^ x;
            root[n] = ++ idx;
            insert(n, 23, root[n - 1], root[n]);
        }
        else
        {
            scanf("%d%d%d", &l, &r, &x);
            printf("%d\n", query(root[r - 1], s[n] ^ x, l - 1));
        }
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/168518/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

255. K decimal

Given A sequence of integers of length N, the subscript is 1 ∼ n.

Now, M operations are to be performed, in which the ith operation is to give three integers li,ri,ki, and find the number of the smallest ki in A[li],A[li+1],..., A[ri] (i.e. the subscript interval [li,ri] of A).

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 100010, M = 10010;

int n, m;
int a[N];
vector<int> nums;

struct Node
{
    int l, r;
    int cnt;
}tr[N * 4 + N * 17];

int root[N], idx;

int find(int x)
{
    return lower_bound(nums.begin(), nums.end(), x) - nums.begin();
}

int build(int l, int r)
{
    int p = ++ idx;
    if (l == r) return p;
    int mid = l + r >> 1;
    tr[p].l = build(l, mid), tr[p].r = build(mid + 1, r);
    return p;
}

int insert(int p, int l, int r, int x)
{
    int q = ++ idx;
    tr[q] = tr[p];
    if (l == r)
    {
        tr[q].cnt ++ ;
        return q;
    }
    int mid = l + r >> 1;
    if (x <= mid) tr[q].l = insert(tr[p].l, l, mid, x);
    else tr[q].r = insert(tr[p].r, mid + 1, r, x);
    tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt;
    return q;
}

int query(int q, int p, int l, int r, int k)
{
    if (l == r) return r;
    int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
    int mid = l + r >> 1;
    if (k <= cnt) return query(tr[q].l, tr[p].l, l, mid, k);
    else return query(tr[q].r, tr[p].r, mid + 1, r, k - cnt);
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ )
    {
        scanf("%d", &a[i]);
        nums.push_back(a[i]);
    }

    sort(nums.begin(), nums.end());
    nums.erase(unique(nums.begin(), nums.end()), nums.end());

    root[0] = build(0, nums.size() - 1);

    for (int i = 1; i <= n; i ++ )
        root[i] = insert(root[i - 1], 0, nums.size() - 1, find(a[i]));

    while (m -- )
    {
        int l, r, k;
        scanf("%d%d%d", &l, &r, &k);
        printf("%d\n", nums[query(root[r], root[l - 1], 0, nums.size() - 1, k)]);
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/168534/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

ac automata

1282. Search keywords

Give n words consisting of lowercase English letters with a length of no more than 50 and an article with a length of m.

Excuse me, how many words appear in the article.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010, S = 55, M = 1000010;

int n;
int tr[N * S][26], cnt[N * S], idx;
char str[M];
int q[N * S], ne[N * S];

void insert()
{
    int p = 0;
    for (int i = 0; str[i]; i ++ )
    {
        int t = str[i] - 'a';
        if (!tr[p][t]) tr[p][t] = ++ idx;
        p = tr[p][t];
    }
    cnt[p] ++ ;
}

void build()
{
    int hh = 0, tt = -1;
    for (int i = 0; i < 26; i ++ )
        if (tr[0][i])
            q[ ++ tt] = tr[0][i];

    while (hh <= tt)
    {
        int t = q[hh ++ ];
        for (int i = 0; i < 26; i ++ )
        {
            int p = tr[t][i];
            if (!p) tr[t][i] = tr[ne[t]][i];
            else
            {
                ne[p] = tr[ne[t]][i];
                q[ ++ tt] = p;
            }
        }
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T -- )
    {
        memset(tr, 0, sizeof tr);
        memset(cnt, 0, sizeof cnt);
        memset(ne, 0, sizeof ne);
        idx = 0;

        scanf("%d", &n);
        for (int i = 0; i < n; i ++ )
        {
            scanf("%s", str);
            insert();
        }

        build();

        scanf("%s", str);

        int res = 0;
        for (int i = 0, j = 0; str[i]; i ++ )
        {
            int t = str[i] - 'a';
            j = tr[j][t];

            int p = j;
            while (p)
            {
                res += cnt[p];
                cnt[p] = 0;
                p = ne[p];
            }
        }

        printf("%d\n", res);
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/169821/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

1285. Words

Someone reads a paper. A paper is made up of many words.

But he found that a word would appear many times in the paper. Now he wanted to know how many times each word appeared in the paper.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1000010;

int n;
int tr[N][26], f[N], idx;
int q[N], ne[N];
char str[N];
int id[210];

void insert(int x)
{
    int p = 0;
    for (int i = 0; str[i]; i ++ )
    {
        int t = str[i] - 'a';
        if (!tr[p][t]) tr[p][t] = ++ idx;
        p = tr[p][t];
        f[p] ++ ;
    }
    id[x] = p;
}

void build()
{
    int hh = 0, tt = -1;
    for (int i = 0; i < 26; i ++ )
        if (tr[0][i])
            q[ ++ tt] = tr[0][i];

    while (hh <= tt)
    {
        int t = q[hh ++ ];
        for (int i = 0; i < 26; i ++ )
        {
            int &p = tr[t][i];
            if (!p) p = tr[ne[t]][i];
            else
            {
                ne[p] = tr[ne[t]][i];
                q[ ++ tt] = p;
            }
        }
    }
}

int main()
{
    scanf("%d", &n);

    for (int i = 0; i < n; i ++ )
    {
        scanf("%s", str);
        insert(i);
    }

    build();

    for (int i = idx - 1; i >= 0; i -- ) f[ne[q[i]]] += f[q[i]];

    for (int i = 0; i < n; i ++ ) printf("%d\n", f[id[i]]);

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/169866/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

splay

955. Maintenance sequence

Please write a program to maintain a sequence, which supports 6 operations:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 500010, INF = 1e9;

int n, m;
struct Node
{
    int s[2], p, v;
    int rev, same;
    int size, sum, ms, ls, rs;

    void init(int _v, int _p)
    {
        s[0] = s[1] = 0, p = _p, v = _v;
        rev = same = 0;
        size = 1, sum = ms = v;
        ls = rs = max(v, 0);
    }
}tr[N];
int root, nodes[N], tt;
int w[N];

void pushup(int x)
{
    auto &u = tr[x], &l = tr[u.s[0]], &r = tr[u.s[1]];
    u.size = l.size + r.size + 1;
    u.sum = l.sum + r.sum + u.v;
    u.ls = max(l.ls, l.sum + u.v + r.ls);
    u.rs = max(r.rs, r.sum + u.v + l.rs);
    u.ms = max(max(l.ms, r.ms), l.rs + u.v + r.ls);
}

void pushdown(int x)
{
    auto &u = tr[x], &l = tr[u.s[0]], &r = tr[u.s[1]];
    if (u.same)
    {
        u.same = u.rev = 0;
        if (u.s[0]) l.same = 1, l.v = u.v, l.sum = l.v * l.size;
        if (u.s[1]) r.same = 1, r.v = u.v, r.sum = r.v * r.size;
        if (u.v > 0)
        {
            if (u.s[0]) l.ms = l.ls = l.rs = l.sum;
            if (u.s[1]) r.ms = r.ls = r.rs = r.sum;
        }
        else
        {
            if (u.s[0]) l.ms = l.v, l.ls = l.rs = 0;
            if (u.s[1]) r.ms = r.v, r.ls = r.rs = 0;
        }
    }
    else if (u.rev)
    {
        u.rev = 0, l.rev ^= 1, r.rev ^= 1;
        swap(l.ls, l.rs), swap(r.ls, r.rs);
        swap(l.s[0], l.s[1]), swap(r.s[0], r.s[1]);
    }
}

void rotate(int x)
{
    int y = tr[x].p, z = tr[y].p;
    int k = tr[y].s[1] == x;
    tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z;
    tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;
    tr[x].s[k ^ 1] = y, tr[y].p = x;
    pushup(y), pushup(x);
}

void splay(int x, int k)
{
    while (tr[x].p != k)
    {
        int y = tr[x].p, z = tr[y].p;
        if (z != k)
            if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x);
            else rotate(y);
        rotate(x);
    }
    if (!k) root = x;
}

int get_k(int k)
{
    int u = root;
    while (u)
    {
        pushdown(u);
        if (tr[tr[u].s[0]].size >= k) u = tr[u].s[0];
        else if (tr[tr[u].s[0]].size + 1 == k) return u;
        else k -= tr[tr[u].s[0]].size + 1, u = tr[u].s[1];
    }
}

int build(int l, int r, int p)
{
    int mid = l + r >> 1;
    int u = nodes[tt -- ];
    tr[u].init(w[mid], p);
    if (l < mid) tr[u].s[0] = build(l, mid - 1, u);
    if (mid < r) tr[u].s[1] = build(mid + 1, r, u);
    pushup(u);
    return u;
}

void dfs(int u)
{
    if (tr[u].s[0]) dfs(tr[u].s[0]);
    if (tr[u].s[1]) dfs(tr[u].s[1]);
    nodes[ ++ tt] = u;
}

int main()
{
    for (int i = 1; i < N; i ++ ) nodes[ ++ tt] = i;
    scanf("%d%d", &n, &m);
    tr[0].ms = w[0] = w[n + 1] = -INF;
    for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
    root = build(0, n + 1, 0);

    char op[20];
    while (m -- )
    {
        scanf("%s", op);
        if (!strcmp(op, "INSERT"))
        {
            int posi, tot;
            scanf("%d%d", &posi, &tot);
            for (int i = 0; i < tot; i ++ ) scanf("%d", &w[i]);
            int l = get_k(posi + 1), r = get_k(posi + 2);
            splay(l, 0), splay(r, l);
            int u = build(0, tot - 1, r);
            tr[r].s[0] = u;
            pushup(r), pushup(l);
        }
        else if (!strcmp(op, "DELETE"))
        {
            int posi, tot;
            scanf("%d%d", &posi, &tot);
            int l = get_k(posi), r = get_k(posi + tot + 1);
            splay(l, 0), splay(r, l);
            dfs(tr[r].s[0]);
            tr[r].s[0] = 0;
            pushup(r), pushup(l);
        }
        else if (!strcmp(op, "MAKE-SAME"))
        {
            int posi, tot, c;
            scanf("%d%d%d", &posi, &tot, &c);
            int l = get_k(posi), r = get_k(posi + tot + 1);
            splay(l, 0), splay(r, l);
            auto& son = tr[tr[r].s[0]];
            son.same = 1, son.v = c, son.sum = c * son.size;
            if (c > 0) son.ms = son.ls = son.rs = son.sum;
            else son.ms = c, son.ls = son.rs = 0;
            pushup(r), pushup(l);
        }
        else if (!strcmp(op, "REVERSE"))
        {
            int posi, tot;
            scanf("%d%d", &posi, &tot);
            int l = get_k(posi), r = get_k(posi + tot + 1);
            splay(l, 0), splay(r, l);
            auto& son = tr[tr[r].s[0]];
            son.rev ^= 1;
            swap(son.ls, son.rs);
            swap(son.s[0], son.s[1]);
            pushup(r), pushup(l);
        }
        else if (!strcmp(op, "GET-SUM"))
        {
            int posi, tot;
            scanf("%d%d", &posi, &tot);
            int l = get_k(posi), r = get_k(posi + tot + 1);
            splay(l, 0), splay(r, l);
            printf("%d\n", tr[tr[r].s[0]].sum);
        }
        else printf("%d\n", tr[root].ms);
    }

    return 0;
}

Author: yxc
 Link: https://www.acwing.com/activity/content/code/content/479402/
Source: AcWing
 The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Posted by dotwebbie on Sun, 19 Sep 2021 23:25:31 -0700