zoukankan      html  css  js  c++  java
  • 对于近期学习上的复习与整理

    近期学了一些新算法,并查集,最短路,线段树,树状数组,最小生成树,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);
    #define putll(n) printf("%lld
    ",n);
    #define putd(n) printf("%lfd
    ",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
    ",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 "); else printf("%d ",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
    ");
            }
            else{
                printf("YES
    ");
            }
        }
        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("
    ");
            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
    ",path[i]);
                    else
                        printf("%d ",path[i]);
                }
                printf("Ticket Not Used
    %d
    ",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
    ",path[i]);
                    else
                        printf("%d ",path[i]);
                }
                printf("%d
    %d
    ",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
    ",ans);
    	else printf("?
    ");
    }
    }
     

    次小生成树

    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
    ", 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:
    ",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
    ",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
    ",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 << '
    ';
        }
        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
    ", 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.
    ", 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
    ", querymax(l, r, 1, n, 1) - querymin(l, r, 1, n, 1));
            }
        }
        return 0;
    }

    简单DP

    策略,转移,具体补充

  • 相关阅读:
    在python3.7下怎么安装matplotlib与numpy
    kNN(从文本文件中解析数据)
    k-近邻算法(kNN)笔记
    第二章--k-近邻算法(kNN)
    C++学习笔记一 —— 两个类文件互相引用的处理情况
    (转) C++中基类和派生类之间的同名函数的重载问题
    初试 Matlab 之去除水印
    (转) linux之sort用法
    vim 简单配置
    hdu 5358 First One
  • 原文地址:https://www.cnblogs.com/DWVictor/p/10421503.html
Copyright © 2011-2022 走看看