对于近期学习上的复习与整理

近期学了一些新算法,并查集,最短路,线段树,树状数组,最小生成树,KMP,简单DP。

暂时就对以上这些算法进行总结与复习。

一、并查集

并查集是最简单的一种算法。

主要用于合并,查找。

基本代码

int par[N];        //父亲
int Rank[N];    //树的高度
int vis[N]; 

bool flag;

void init(int n)
{
    for(int i=0; i<=n; ++i)
    {
        par[i] = i;
        vis[i] = 0;
    }
}
int find(int a)
{
    int r = a;
    while(par[r] != r)
    r = par[r];
    int i = a;
    int j;
    while(i != r)
    {
        j = par[i];
        par[i] = r;
        i = j;
    }
    return r;
}
void merge(int a,int b)
{
    int A,B;
    A =  find(a);
    B =  find(b);
    if(A != B)
    {
        par[B] = A;
    }
    else
    {
        flag = 0;
    }
}

 

int par[N];        //父亲
int Rank[N];    //树的高度

//初始化n个元素
void init(int n)
{
    for(int i=0; i<=n; ++i)
    {
        par[i] = i;
        Rank[i] = 0;
    }
}
//查询树的根非递归实现
int find(int x)
{
    while(par[x]!=x)
        x=par[x];
    return x;
}
//合并x和y所属集合
void unite(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx==fy)
        return;
    if(Rank[fx]>Rank[fy])
        par[fx]=fy;
    else
    {
        par[fy]=fx;
        if(Rank[fx]==Rank[fy])
            Rank[x]++;
    }
}
//关于路径压缩
int find2(int x)
{
    int fx=find(x);
    int t;
    while(x!=fx)
    {
        t=par[x];
        par[x]=fx;
        x=t;
    }
    return fx;
}

 

How Many Tables

 

/**
/*@author Victor
/*language C++
*/
//#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
#define iput(n) scanf("%d",&n);
#define dput(n) scanf("%lf",&n);
#define llput(n) scanf("%lld",&n);
#define puti(n) printf("%d\n",n);
#define putll(n) printf("%lld\n",n);
#define putd(n) printf("%lfd\n",n);
int par[N];        //父亲
int Rank[N];    //树的高度

//初始化n个元素
void init(int n)
{
    for(int i=0; i<=n; ++i)
    {
        par[i] = i;
        Rank[i] = 0;
    }
}
//查询树的根非递归实现
int find(int x)
{
    while(par[x]!=x)
        x=par[x];
    return x;
}
//合并x和y所属集合
void unite(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx==fy)
        return;
    if(Rank[fx]>Rank[fy])
        par[fx]=fy;
    else
    {
        par[fy]=fx;
        if(Rank[fx]==Rank[fy])
            Rank[x]++;
    }
}
//关于路径压缩
int find2(int x)
{
    int fx=find(x);
    int t;
    while(x!=fx)
    {
        t=par[x];
        par[x]=fx;
        x=t;
    }
    return fx;
}

int main()
{
#ifdef DEBUG
    freopen("input.in", "r", stdin);
    //freopen("output.out", "w", stdout);
#endif

    int T;
    iput(T)
    //scanf("%d",&T);
    while(T--)
    {
        int n, m;
        iput(n)
        iput(m)
        //scanf("%d%d",&n,&m);
        init(n);
        for(int i = 0; i < m; i++)
        {
            int a,b;
            //
            iput(a)
            iput(b)
            //    scanf("%d%d",&a,&b);
            unite(a,b);
        }
        int sum = 0;
        for(int i = 1; i <= n; i++)
        {
            if(find(i)==i)
                sum++;
        }
        puti(sum)
        //printf("%d\n",sum);

    }
}

 

最短路Dijkstra

const int maxn = 1200;

int mp[maxn][maxn],dis[maxn],vis[maxn];
int k[maxn];
int n,m;
void dijkstra(int x){
//初始化    
    for(int i = 0; i < n;i++){
        dis[i] = mp[x][i];
        vis[i] = 0;
    }
dis[x]
= 0; vis[x] = 1; int j,k,temp; for(int i = 0;i < n;i++){ temp = INF; //又是循环写错 for(int j = 0;j < n;j++){ if(!vis[j]&&(temp > dis[j])){ k = j; temp = dis[j]; } } if(temp==INF) break; vis[k] = 1; for(int i = 0;i < n;i++){ if(!vis[i]&&(dis[i]>(dis[k]+mp[k][i]))) dis[i] = dis[k] + mp[k][i]; } } } int main(){ while(~scanf("%d%d",&n,&m)){ for(int i = 0;i < n;i++){ for(int j = 0;j < n ;j++){ mp[i][j] = INF; } } for(int i = 0;i < m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); if(mp[u][v] > w){ mp[u][v] = mp[v][u] = w; } } int s,t; scanf("%d%d",&s,&t); dijkstra(s); if(dis[t]==INF) printf("-1\n"); else printf("%d\n",dis[t]); } }

dj是来记录从s出发到每一点的最短路

 

spfa判负环以及建图

int n , m ,tot,k;
int head[N*10];
struct node{
int from;
int to;
int w;
int next; 
}edge[N*10];
int dis[N*10],cnt[N*10],path[N*10];
bool inq[N*10];
void init(){
    memset(head,-1,sizeof(head));
    tot = 0;
}

void add(int from,int to,int w){
    
    edge[tot].from = from;
    edge[tot].to = to;
    edge[tot].w = w;
    edge[tot].next = head[from];
    head[from] = tot++;
    
}
//判负权边 
bool spfa(int st){
    //双向 
    deque<int>q;
    __cls(dis);
    _cls(inq);
    _cls(cnt);
    dis[st] = 0;
    q.push_back(st);
    inq[st] = true;
    cnt[st]++;
    while(!q.empty()){
        int now = q.front();
        q.pop_front();
        inq[now] = 0;
        if(cnt[now] >= n){
            return false;
        }
    for(int i = head[now];i!=-1;i = edge[i].next){
        int nex = edge[i].to;
        if(dis[nex] > dis[now] + edge[i].w){
            dis[nex] = dis[now] + edge[i].w;
            if(!inq[nex]){
                inq[nex] = 1;
                cnt[nex]++;
                if(!q.empty()&&dis[nex] < dis[q.front()]){
                    q.push_front(nex);
                }
                else{
                    q.push_back(nex);
                }
            }
        }
    }    
        
    }
    return true;
} 

int main(){
    
    int t,u,v,w;
    iput(t)
    for(int i = 1; i <= t; i++){
        iput(n)
        iput(m)
        iput(k)
        init();
        while(m--){
            iput(u)
            iput(v)
            iput(w)
            add(u,v,w);
            add(v,u,w);
        }
        while(k--){
            iput(u)
            iput(v)
            iput(w)
            add(u,v,-w);
        }
        if(spfa(1)){
            printf("NO\n");
        }
        else{
            printf("YES\n");
        }
    }
    return 0;
}

 

最短路 队列 建图

struct Edge
{
    int to;
    int dis;
    Edge(int to,int dis)
    {
        this -> to = to;
        this -> dis = dis;
    }
};

vector<Edge>mp[maxn];

typedef pair<int,int>P;

void init()
{
    start = -1;
    cnt=0;
    for(int i = 0; i < maxn; i++)
        mp[i].clear();
    ___cls(shead);
    ___cls(ehead);
    fill(sdis + 1,sdis + 1 + n,INF);
    fill(edis + 1,edis + 1 + n,INF);
}

void dijkstra(int dis[],int head[],int s)
{
    priority_queue<P,vector<P>,greater<P> >q;
    while(!q.empty())
        q.pop();
    dis[s] = 0;
    q.push(P(0,s));
    while(!q.empty())
    {
        P p = q.top();
        q.pop();
        int v = p.second;
        if(p.first > dis[v])
            continue;
        for(int i = 0; i < mp[v].size(); i++)
        {
            Edge& e = mp[v][i];
            if(dis[v] + e.dis < dis[e.to])
            {
                head[e.to] = v;
                dis[e.to] = dis[v] + e.dis;
                q.push(P(dis[e.to],e.to));
            }
        }
    }
}

void doit()
{
    dijkstra(sdis,shead,S);
    dijkstra(edis,ehead,E);
    ans = sdis[E];
}


int main()
{
    while(scanf("%d%d%d",&n,&S,&E)!=EOF)
    {
        init();
        scanf("%d",&M);
        for(int i = 0; i< M; i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            mp[x].push_back(Edge(y,z));
            mp[y].push_back(Edge(x,z));
        }
        doit();
        scanf("%d",&k);
        for(int i = 0; i < k; i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            if(sdis[x] + edis[y] + z < ans)
            {
                start = x;
                End = y;
                ans = sdis[x] + edis[y] + z ;
            }
            if(sdis[y] + edis[x] + z < ans)
            {
                start = y;
                End = x;
                ans = sdis[y] + edis[x] + z;
            }
        }

        if(cas)
            printf("\n");
        cas++;
        if(start == -1)
        {
            for(int i = E; ~i; i=shead[i])
                path[cnt++] = i;
            for(int i = cnt-1; i >= 0; i--)
            {
                if(i == 0)
                    printf("%d\n",path[i]);
                else
                    printf("%d ",path[i]);
            }
            printf("Ticket Not Used\n%d\n",ans);
        }
        else
        {
            for(int i = start; ~i; i = shead[i])
                path[cnt++] = i;
            reverse(path,path+cnt);
            for(int i = End; ~i; i = ehead[i])
                path[cnt++] = i;
            for(int i = 0; i < cnt; i++)
            {
                if(i == cnt-1)
                    printf("%d\n",path[i]);
                else
                    printf("%d ",path[i]);
            }
            printf("%d\n%d\n",start,ans);
        }
    }
    return 0;
}

 

 

using namespace std;
const ll maxn=200000+10;
const ll INF=1LL<<60;
ll SUM[maxn];
ll n,m,t;
ll head[maxn],cnt;
struct edge
{
    ll a;
    ll to,b,next;
}mp[maxn];

void add(ll from,ll to,ll a,ll b)
{
    mp[++cnt].next = head[from];
    mp[cnt].to = to;
    mp[cnt].a = a;
    mp[cnt].b = b;
    head[from] = cnt;
}

struct EDGE
{
    ll dis;
    ll to;
    EDGE(ll a,ll b)
    {
        to = a;
        dis = b;
    }
    bool operator <(const EDGE &k)const
    {
        return dis > k.dis;
    }
};

void init()
{
    SUM[0]=1;
    for(ll i = 1;i <= 100;i++) SUM[i] = SUM[i-1]<<1;
}

ll dis[maxn];

void dijkstra(ll s)
{
    bool vis[maxn];
    
    for(ll i = 0;i <= n;i++) dis[i] = INF;
    for(ll i = 0;i <= n;i++) vis[i] =  false;
    
    dis[s] = 1;
    priority_queue<EDGE>q;
    q.push(EDGE(s,dis[s]));
    while(!q.empty())
    {
        EDGE top = q.top();
        q.pop();
        if(vis[top.to]) continue;
        vis[top.to] = true;
        for(ll i = head[top.to];i;i=mp[i].next)
        {
            edge tmp = mp[i];
            if(tmp.a / dis[top.to] +1 < SUM[tmp.b])continue;
            if(dis[tmp.to] > tmp.a + dis[top.to])
            {
                dis[tmp.to] = tmp.a + dis[top.to];
                q.push(EDGE(tmp.to,dis[tmp.to]));
            }
        }
    }
}

 

最小生成树

struct edge
{
    int u,v,cost;
}eg[100001];
int n,m;//,father[100001];
 
bool cmp(edge e1,edge e2)
{
    return e1.cost<e2.cost;
}

int par[N];        //父亲
int Rank[N];    //树的高度

//初始化n个元素
void init(int n)
{
    for(int i=0; i<=n; ++i)
    {
        par[i] = i;
        Rank[i] = 0;
    }
}
//查询树的根非递归实现
int find(int x)
{
    while(par[x]!=x)
        x=par[x];
    return x;
}
//合并x和y所属集合
void unite(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx==fy)
        return;
    if(Rank[fx]>Rank[fy])
        par[fx]=fy;
    else
    {
        par[fy]=fx;
        if(Rank[fx]==Rank[fy])
            Rank[x]++;
    }
}
//关于路径压缩
int find2(int x)
{
    int fx=find(x);
    int t;
    while(x!=fx)
    {
        t=par[x];
        par[x]=fx;
        x=t;
    }
    return fx;
}

// 最小生成树 Kruskal 算法
int Kruskal(  )
{
    edge e;
    int i,res;
    sort(eg,eg+n,cmp);
    // 并查集 初始化
    init(m);
 
    // 构建最小生成树
    res=0;
    for( i=0;i<n;++i )
    {
        e=eg[i];
        if( find(e.u)!=find(e.v) )
        {
            unite(e.u,e.v);
            res+=e.cost;
        }
    }
    return res;
}
int main(){
//	int n,m;
	while(scanf("%d%d",&n,&m)&&n){
	
	for(int i = 0; i < n;++i){
		scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].cost);
	}
	int ans = Kruskal();
	bool flag = 1;
	for(int i = 2 ;i <= m;i++){
		if(find(1)!=find(i)){
			flag = 0;
			break;
		}
	}
	if(flag) printf("%d\n",ans);
	else printf("?\n");
}
}
 

 

次小生成树

const int N = 1000 + 7 ;
int t, n, p[N], pre[N];
double ans, MST, e[N][N], g[N][N], x[N], y[N], dis[N];
bool vis[N], used[N][N];

double get_dis(double a, double b, double c, double d)
{
    return sqrt((a - c) * (a - c) + (b - d) * (b - d));
}

void prim()
{
    memset(vis, 0, sizeof(vis));
    memset(used, 0, sizeof(used));
    memset(g, 0, sizeof(g));

    for(int i = 1 ; i <= n; ++i  )
    {
        dis[i] = e[1][i], pre[i] = 1;

    }
    for(int i = 1; i <= n ; ++i)
    {
        int u = -1;
        for(int j = 1; j <= n; ++j)
        {
            if(!vis[j] && (u == -1 || dis[j] < dis[u]))
                u = j;

        }
        MST += dis[u];
        vis[u] = 1;
        used[u][pre[u]] = used[pre[u]][u] = 1;
        for(int j = 1; j <= n; ++j)
        {
            if(vis[j] && j != u)
                g[u][j] = g[j][u] = max(g[j][pre[u]], dis[u]);
            if(!vis[j] && e[u][j] < dis[j])
                dis[j] = e[u][j], pre[j] = u;

        }
    }
}


int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
            scanf("%lf%lf%d", &x[i], &y[i], &p[i]);
        for(int i = 1; i < n; ++i)
            for(int j = i + 1 ; j <= n; ++j)
                e[i][j] = e[j][i] = get_dis(x[i], y[i], x[j], y[j]);
        MST = 0;
        ans = -1;
        prim();
        for(int i = 1 ; i < n ; ++i )
            for(int j = i + 1 ; j <= n ; ++j)
                if(used[i][j])
                    ans = max(ans, (p[i] + p[j] ) / (MST - e[i][j]));
                else
                    ans = max(ans, (p[i] + p[j]) / (MST - g[i][j]));
        printf("%.2lf\n", ans);
    }
    return 0;
}

 

线段树

/**
/*@author Victor 
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 200020;

struct Note{
    int r,l,sum;
    
}tree[N<<2];
//建树 

void buildtree(int l,int r, int pos){
    tree[pos].l = l;
    tree[pos].r = r;
    if(l == r){
        scanf("%d",&tree[pos].sum);
        return ;
        //某q强调的 
    }
    int mid = (l + r) /2;
    buildtree(l ,mid ,pos<<1);//建立左右子树
    buildtree(mid+1,r,pos<<1|1);
    tree[pos].sum = tree[pos<<1].sum + tree[pos<<1|1].sum; 
     }
     
     //结点更新
     void update(int p,int c , int pos){
     //    if(tree[pos].l == tree[pos].r&&tree[pos].l==p){
             if(tree[pos].l==tree[pos].r&&tree[pos].l==p){
                 tree[pos].sum += c;
                 return ;
                 
             }
             int mid = (tree[pos].l + tree[pos].r)/2;
             if(p <= mid)
             update(p,c,pos<<1);//更新左右节点 
             else update(p,c,pos<<1|1);
             tree[pos].sum = tree[pos<<1].sum + tree[pos<<1|1].sum;
         }
//     } 
     
     //点查询 -> query
     
     int query(int l ,int r , int pos){
         
         if(tree[pos].l==l&&tree[pos].r==r)
         return tree[pos].sum;
         int mid = (tree[pos].l + tree[pos].r)/2;
         if(r <= mid)
         return query(l,r,pos*2);
         else if(l > mid)
         return query(l,r,pos<<1|1);
         else 
         return query(l,mid,pos<<1) + query(mid+1,r,pos<<1|1); 
     } 
int main(){
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int t;
    scanf("%d",&t);
    int cas = 1;
    while(t--){
        int n;
        scanf("%d",&n);
    printf("Case %d:\n",cas++);    
    buildtree(1,n,1);
    while(1){
        char str[20];
        scanf("%s",str);
        if(str[0]=='E')
        break;
        else if(str[0]=='Q'){
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            printf("%d\n",query(t1,t2,1));
        }
        else if(str[0]=='S'){
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            update(t1,-t2,1);
        }
        else if(str[0]=='A'){
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            update(t1,t2,1);
        }
    }
    
    }
    return 0;
} 

 

线段树

/**
/*@author ~victor~
*/
#include <bits/stdc++.h>
using namespace std;
#define maxsize 200020
typedef struct
{
    int left,right;
    int maxn;
}Node;
int n,m;
int num[maxsize];
Node tree[maxsize*20];
int buildtree(int root,int left,int right)// 构建线段树 
{
    int mid;
    tree[root].left=left;
    tree[root].right=right;// 当前节点所表示的区间 
    if(left==right)// 左右区间相同,则此节点为叶子,max 应储存对应某个学生的值 
        return tree[root].maxn=num[left];
    mid=(left+right)/2;
    int a,b;// 递归建立左右子树,并从子树中获得最大值
    a=buildtree(2*root,left,mid);
    b=buildtree(2*root+1,mid+1,right);
    return tree[root].maxn=max(a,b);
}
int find(int root,int left,int right)// 从节点 root 开始,查找 left 和 right 之间的最大值
{
    int mid;
    if(tree[root].left>right||tree[root].right<left)// 若此区间与 root 所管理的区间无交集
        return 0;
    if(left<=tree[root].left&&tree[root].right<=right)// 若此区间包含 root 所管理的区间
        return tree[root].maxn;
    mid=(left+right)/2;
    int a,b;// 若此区间与 root 所管理的区间部分相交 
    a=find(2*root,left,right);
    b=find(2*root+1,left,right);
    return max(a,b);
}
int update(int root,int pos,int val)// 更新 pos 点的值
{
    if(pos<tree[root].left||pos>tree[root].right)// 若 pos 不存在于 root 所管理的区间内
        return tree[root].maxn;
    if(tree[root].left==pos&&tree[root].right==pos)// 若 root 正好是一个符合条件的叶子
        return tree[root].maxn=val;
    int a,b;// 否则。。。。
    a=update(2*root,pos,val);
    b=update(2*root+1,pos,val);
    tree[root].maxn=max(a,b);
    return tree[root].maxn;
}
int main()
{
    char c;
    int i;
    int x,y;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=1;i<=n;i++)
            scanf("%d",&num[i]);
        buildtree(1,1,n);
        for(i=1;i<=m;i++)
        {
            getchar();
            scanf("%c%d%d",&c,&x,&y);
            if(c=='Q')
                printf("%d\n",find(1,x,y));
            else
            {
                num[x]=y;
                update(1,x,y);
            }
        }
    }
    return 0;
}

 

树状数组

/**
/*@author victor
/*
*/
#include<bits/stdc++.h>
#define lowbit(x) x&-x
using namespace std;
const int maxn = 5050;
int c[maxn];
int n;

void add(int i,int x)
{
    while(i <= n)
    {
        c[i] += x;
        i+=lowbit(i);
    }
}

int sum(int i)
{
    int tmp = 0;
    while(i > 0)
    {
        tmp += c[i];
        i -= lowbit(i);
    }
    return tmp;
}

int a[maxn];
#define _cls(a) memset(a,0,sizeof(a))
int main(){
    while(~scanf("%d",&n)){
        int ans = 0;
        _cls(a);
        _cls(c);
        for(int i  = 1;i <= n; i++)
        {
            scanf("%d",&a[i]);
            a[i]++;
            ans += sum(n) - sum(a[i]);
            add(a[i],1);  
        }
        int min = ans;
        for(int i = 1 ; i <= n;i++){
            ans += n - a[i] -(a[i]-1);
            if(ans < min) min = ans;
        }
        cout << min << '\n';
    }
    return 0;
}

 

树状数组add&querry

int main(){
//    freopen("out.txt","w",stdout);
    cin >> n  >> q;
    for(int i = 1 ; i <= n;i++)
    {
    int num;
    scanf("%d",&num);
    add(bit0,i,num);
     } 
    while(q--){
        
        char s[5];
        int l,r,x;
        scanf("%s",s);
        if(s[0]=='C')
        {
            scanf("%d%d%d",&l,&r,&x);
            add(bit0, l, -x*(l-1));
            add(bit1, l, x);
            add(bit0, r+1, x*r);
            add(bit1, r+1, -x);
        }
        else
        {
            scanf("%d%d", &l, &r);
            ll res = 0;
            res += sum(bit0, r) + sum(bit1, r) * r;
            res -= sum(bit0, l-1) + sum(bit1, l-1) * (l - 1);
            printf("%lld\n", res);
        }
    }
    return 0;
}

 

线段树

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int MAXN = 2e5 + 10;
#define lson l,m,i<<1
#define rson m+1,r,i<<1|1
#define length (note[i].r-note[i].l+1)

struct Note
{
    int l, r;
    int mid()
    {
        return (l + r) / 2.0;
    }
};

ll ans;

Note note[MAXN << 2];
ll add[MAXN << 2];
ll sum[MAXN << 2];
void push_up(int i )
{
    sum[i] = sum[i << 1] + sum[i << 1 | 1];
}

void build(int l, int r, int i)
{
    note[i].l = l;
    note[i].r = r;
    sum[i] = 0;
    add[i] = 0;
    if(l == r)
    {
        sum[i] = 1;
        return ;
    }
    int m = note[i].mid();
    build(lson);
    build(rson);
    push_up(i);
}

void push_down(int i, int l)
{

    if(add[i])
    {
        add[i << 1] = add[i];
        add[i << 1 | 1] = add[i];
        sum[i << 1] = add[i] * (l - (l >> 1));
        sum[i << 1 | 1] = add[i] * (l >> 1);
        add[i] = 0;
    }
}

void query(int l, int r, int i)
{
    if(note[i].l == l && note[i].r == r)
    {
        ans += sum[i];
        return ;
    }
    push_down(i, length);
    int m = note[i].mid();
    if(r <= m)
        query(1, r, i << 1);
    else if(l > m)
        query(l, r, i << 1 | 1);
    else
    {
        query(lson);
        query(rson);
    }
}


void update(int l, int r, int i, int v)
{
    if(note[i].l == l && note[i].r == r)
    {
        sum[i] = (ll)v * (r - l + 1);
        add[i] = v;
        return ;
    }
    push_down(i, length);
    int m = note[i].mid();
    if(r <= m)
    {
        update(l, r, i << 1, v);
    }
    else
    {
        if(l > m)
            update(l, r, i << 1 | 1, v);
        else
        {
            update(lson, v);
            update(rson, v);
        }
    }
    push_up(i);
}

int main()
{
    int n, c, d, i, t, m, j, e;
    scanf("%d", &t);
    for(int i = 1; i <= t; i ++)
    {
        scanf("%d", &n);
        build(1, n, 1);
        scanf("%d", &m);
        for(j = 1; j <= m; j++)
        {
            scanf("%d%d%d", &c, &d, &e);
            update(c, d, 1, e);
        }
        ans = 0;
        query(1, n, 1);
        printf("Case %d: The total value of the hook is %d.\n", i, ans);
    }
    return 0;
}

 

RMQ&LCA

#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
#define INF 0x3f3f3f3f
#define MAXN 200005
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 2000000 + 7;
int MAX[maxn << 2], MIN[maxn << 2];
void PushUp(int rt)
{
    MAX[rt] = max(MAX[rt << 1], MAX[rt << 1 | 1]);
    MIN[rt] = min(MIN[rt << 1], MIN[rt << 1 | 1]);
}
void build(int l, int r, int rt)
{
    if(r == l)
    {
        scanf("%d", &MAX[rt]);
        MIN[rt] = MAX[rt];
        return;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUp(rt);
}
int querymax(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        return MAX[rt];
    }
    int m = (l + r) >> 1;
    int ret = 0;
    if(L <= m)
        ret = max(ret, querymax(L, R, lson));
    if(R > m)
        ret = max(ret, querymax(L, R, rson));
    return ret;
}
int querymin(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        return MIN[rt];
    }
    int m = (l + r) >> 1;
    int ret = INF;
    if(L <= m)
        ret = min(ret, querymin(L, R, lson));
    if(R > m)
        ret = min(ret, querymin(L, R, rson));
    return ret;
}
int main()
{
    int n, t;
    while(~scanf("%d%d", &n, &t))
    {
        build(1, n, 1);
        while(t--)
        {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d\n", querymax(l, r, 1, n, 1) - querymin(l, r, 1, n, 1));
        }
    }
    return 0;
}

 

简单DP

策略,转移,具体补充

posted @ 2019-02-23 02:59  DWVictor  阅读(179)  评论(0)    收藏  举报