zoukankan      html  css  js  c++  java
  • 题解

    链接:https://codeforces.ml/gym/294361/problem/A

    题目冗长傻逼。其实很简单,但是如果用spfa有可能会爆栈,所以我们可以通过打标记的方法来解决;

    但是打标记不是很稳定;

    所以考虑dp

    这个其实有点像背包dp,相当于在一个容积下的最小体积。

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cctype>
    #include <queue>
    #include <stdlib.h>
    #include <cstdlib>
    #include <math.h>
    #include <set>
    #include <vector>
    #define inf 107374182
    #define N 1010
    #define M 10010001
    #define ll int
    #define PII pair<int,int>
    using namespace std;
    inline int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    inline ll Max(ll a,ll b){return a>b?a:b;}
    inline ll Min(ll a,ll b){return a<b?a:b;}
    int price[N];
    int dist[N][N];
    int cost[N][N];
    struct Node1{
        int x,y;
    }node1[N];
    
    int head[N],edgenum;
    vector<PII> G[N];
    vector<PII> P[N];
    int n,maxcost,dp[N][N];
    
    int vis[N][N];
    const int INF = (int)1e9;
    int get_dist(int u,int v){
        return ceil(sqrt((node1[u].x - node1[v].x) * (node1[u].x - node1[v].x) + (node1[u].y - node1[v].y) * (node1[u].y - node1[v].y)));
    }
    
    int main()
    {
    	int i,m,u,v,d,w;
        node1[0].x = read(); node1[0].y = read();
        node1[1].x = read(); node1[1].y = read();
        maxcost = read(); maxcost ++;
        price[0] = read();
        int T = read();
        for(int i = 1; i <= T;i ++) price[i] = read();
        n = read();
        for(int i = 2;i < n + 2; i ++){
            node1[i].x = read(); node1[i].y = read();
            int t = read();
            while(t --){
                int x1 = read(),y1 = read();x1 += 2;
                P[i].push_back({x1,y1});
                P[x1].push_back({i,y1});
            }
        }
    
    
        for (int i = 1; i < n + 2; i++) {
    		P[0].push_back({i, 0});
    		if (i > 1) P[i].push_back({1, 0});
    	}
    
        n += 2;
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                dist[i][j] = get_dist(i,j);
            }
        }
        for (int i = 0; i <= n; i++)
    		for (int j = 0; j <= maxcost; j++)
    			dp[i][j] = INF;
        dp[0][0] = 0;
        for(int d = 0; d < maxcost; d ++){
            for(int v = 0; v < n; v ++){
                if(dp[v][d] >= INF) continue;
                for(int j = 0; j < P[v].size(); j ++){
                    PII e = P[v][j];
                    int u = e.first;
                    int t = e.second;
                    int d2 = dist[v][u] + d;
                    if(d2 >= maxcost) continue;
                    dp[u][d2] = min(dp[u][d2], dp[v][d] + dist[v][u] * price[e.second]);
                }
            }
        }
        int ans = INF;
    	for (int i = 0; i < maxcost; i++)
    		ans = min(ans, dp[1][i]);
    	if (ans == INF)
    		printf("-1
    ");
    	else
    		printf("%d
    ", ans);
    	return 0;
    }
    

      链接:https://codeforces.ml/gym/294123/problem/L

    我们可以预处理每个格子能到哪些格子并全部保存下来。

    这样就相当于得到了一张图,在到图上进行bfs找最短路即可,注意保存路径。

    因为要求字符串最小,所以还需要注意顺序。

    #include"stdio.h"
    #include"string.h"
    #include"stack"
    #include"map"
    #include"math.h"
    #include"iostream"
    #include"vector"
    #include"queue"
    #include"algorithm"
    using namespace std;
    #define OK printf("
    ");
    #define Debug printf("this_ok
    ");
    #define INF 1e18
    typedef long long ll;
    #define scanll(a,b) scanf("%lld%lld",&a,&b);
    #define scanl(a) scanf("%lld",&a);
    #define printl(a,b) if(b == 0) printf("%lld ",a); else printf("%lld
    ",a);
    #define print_int(a,b) if(b == 0) printf("%d ",a); else printf("%d
    ",a);
    typedef pair<int,int> PII;
    
    inline int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    const ll mod = 998244353;
    const int N = 2010,M = 300010;
    const  double pi = acos(-1);
    
    int n,m,sx,sy,ex,ey;
    char str[N][N];
    int G[4][N][N];
    int vis[N][N];
    int dis[N][N];
    PII path[N][N];
    int dir[N][N];
    queue<PII> Q;
    
    void bfs(){
       Q.push({sx,sy});
       dis[sx][sy] = 1;
       while(!Q.empty()){
          PII P = Q.front(); Q.pop();
         // printf("%d %d
    ",P.first,P.second);
          for(int i = 0; i < 4; i ++){
            int x = P.first,y = P.second;
            if(i == 0 || i == 3) x = G[i][P.first][P.second];
            else y = G[i][P.first][P.second];
            if(x == 0 || y == 0 || str[x][y] == 'X') continue;
            if(dis[x][y]) continue;
            dis[x][y] = dis[P.first][P.second] + 1;
            dir[x][y] = i;
            path[x][y] = P;
            Q.push({x,y});
          }
       }
    }
    int main(){
        n = read(),m = read();
        for(int i = 1; i <= n;i ++){
            scanf("%s",str[i] + 1);
            for(int j = 1; j <= m; j ++){
                if(str[i][j] == 'S'){
                    sx = i; sy = j;
                }
                if(str[i][j] == 'E'){
                    ex = i; ey = j;
                }
            }
        }
        str[sx][sy] = str[ex][ey] = '.';
        for(int i = n - 1; i >= 1; i --){
            for(int j = 1; j <= m; j ++){
                if(str[i + 1][j] == 'X') G[0][i][j] = G[0][i + 1][j];
                else G[0][i][j] = i + 1;
            }
        }
        for(int i = 1; i <= n; i ++){
            for(int j = 2; j <= m; j ++){
                if(str[i][j - 1] == 'X') G[1][i][j] = G[1][i][j - 1];
                else G[1][i][j] = j - 1;
            }
        }
        for(int i = 1; i <= n; i ++){
            for(int j = m - 1; j >= 1 ; j --){
                if(str[i][j + 1] == 'X') G[2][i][j] = G[2][i][j + 1];
                else G[2][i][j] = j + 1;
            }
        }
        for(int i = 2; i <= n; i ++){
            for(int j = 1; j <= m; j ++){
                if(str[i - 1][j] == 'X') G[3][i][j] = G[3][i - 1][j];
                else G[3][i][j] = i - 1;
            }
        }
        bfs();
        if(dis[ex][ey] == 0) printf("-1
    ");
        else {
            printf("%d
    ",dis[ex][ey] - 1);
            string s;
    		char d[4] = {'D', 'L', 'R', 'U'};
    		while(ex!=sx || ey!=sy){
    			s += d[dir[ex][ey]];
    			int x = path[ex][ey].first;
    			int y = path[ex][ey].second;
    			ex = x; ey = y;
    		}
    		reverse(s.begin(), s.end());
    		printf("%s
    ", s.c_str());
        }
    }
    /*
    3
    1 2 3
    2
    2 6
    */
     
    

      链接:http://poj.org/problem?id=2528

    都是值得离散化在处理,确实也是要离散化在处理,但是没有那么简单;

    1
    2
    1 3
    5 7

    这组样例,杀很多离散化处理代码了。

    所以我们对每个出现过的数字,还要把他们+1的数保存下来,在离散化处理;

    #include"stdio.h"
    #include"string.h"
    #include"stack"
    #include"map"
    #include"math.h"
    #include"iostream"
    #include"vector"
    #include"queue"
    #include"set"
    #include"algorithm"
    using namespace std;
    #define OK printf("
    ");
    #define Debug printf("this_ok
    ");
    #define inf 1e9
    #define INF 1e18
    typedef long long ll;
    #define scanll(a,b) scanf("%lld%lld",&a,&b);
    #define scanl(a) scanf("%lld",&a);
    #define printl(a,b) if(b == 0) printf("%lld ",a); else printf("%lld
    ",a);
    #define print_int(a,b) if(b == 0) printf("%d ",a); else printf("%d
    ",a);
    typedef pair<int,int> PII;
    inline int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    const ll mod = 998244353;
    const int N = 300100;
    int n,a[N],b[N],op[N][2],top,len;
    int root,lc[N << 4],rc[N << 4],tot,val[N << 4],laze[N << 4];
    
    void push_down(int rt){
        if(laze[rt] == 0) {
            return ;
        }
        val[lc[rt]] = val[rc[rt]] = laze[rt];
        laze[lc[rt]] = laze[rc[rt]] = laze[rt];
        laze[rt] = 0;
    }
    void Build_Tree(int &rt,int l,int r){
        rt = ++ tot; val[rt] = 0; laze[rt] = 0;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        Build_Tree(lc[rt],l,mid);
        Build_Tree(rc[rt],mid + 1,r);
    }
    void Update(int rt,int L,int R,int l,int r,int color){
        if(l <= L && r >= R){
            laze[rt] = color; val[rt] = color;
            return ;
        }
        push_down(rt);
        int mid = (L + R) >> 1;
        if(l <= mid) Update(lc[rt],L,mid,l,r,color);
        if(r > mid)  Update(rc[rt],mid + 1,R,l,r,color);
    }
    int query(int rt,int L,int R,int pos){
        if(L == R) return val[rt];
        int mid = (L + R) >> 1;
        push_down(rt);
        if(pos <= mid) return query(lc[rt],L,mid,pos);
        else return query(rc[rt],mid + 1,R,pos);
    }
    int main(){
        int T = read();
        while(T --){
            n = read(); set<int> Q; tot = 0; top = 0;
            for(int i = 1; i <= n; i ++){
                op[i][0] = read(); op[i][1] = read();
                a[++ top] = op[i][0]; b[top] = a[top];
                a[++ top] = op[i][1]; b[top] = a[top];
                a[++ top] = op[i][0] + 1; b[top] = a[top];
                a[++ top] = op[i][1] + 1; b[top] = a[top];
            }
            sort(b + 1,b + top + 1);
            len = unique(b + 1,b + top + 1) - b - 1;
            Build_Tree(root,1,len);
            for(int i = 1;i <= n; i ++){
                int l = lower_bound(b + 1,b + len + 1,op[i][0]) - b;
                int r = lower_bound(b + 1,b + len + 1,op[i][1]) - b;
                Update(root,1,len,l,r,i);
            }
    
            int ans = 0;
        //    printf("%d
    ",len);
            for(int i = 1;i <= len; i ++){
               int x = query(root,1,len,i);
             //  printf("x = %d b[i] = %d
    ",x,b[i]);
               if(x >= 1 && x <= n)
               Q.insert(x);
            }
            printf("%d
    ",Q.size());
        }
    }
    /*
    3
    1 2 3
    2
    2 6
    */
    

      链接:http://acm.hdu.edu.cn/showproblem.php?pid=6430

    这个题有点东西。我们发现1-100000中的因子数量只有200多。所以我们对每个点都建立一个1-100000的权值线段树,同时从叶子结点向上进行合并。

    在合并的过程中,不断的更新答案。

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cctype>
    #include <queue>
    #include <stdlib.h>
    #include <cstdlib>
    #include <math.h>
    #include <set>
    #include <vector>
    #define inf 107374182
    #define M 10010001
    #define ll int
    #define PII pair<int,int>
    using namespace std;
    inline int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    const int N = 200200;
    int n,a[N];
    int head[N],ver[N * 400],Next[N * 400],tot,ans[N];
    vector<int>F[N];
    int maxx;
    int root[N],lson[N * 400],rson[N * 400],val[N * 400],top;
    
    void add(int x,int y){
        ver[++ tot] = y; Next[tot] = head[x]; head[x] = tot;
    }
    void init(){
        for(int i = 1; i <= 100100; i ++){
            for(int j = i; j <= 100100; j += i)
                F[j].push_back(i);
        }
    }
    
    void Update(int &rt,int l,int r,int x){
        if(rt == 0) rt = ++ top;
        if(l == r) {val[rt] = x;return ;}
        int mid = (l + r) >> 1;
        if(x <= mid) Update(lson[rt],l,mid,x);
        else Update(rson[rt],mid + 1,r,x);
        val[rt] = max(val[lson[rt]],val[rson[rt]]);
    }
    int Merge(int rtx,int rty,int l,int r,int u){
        if(!rtx || !rty) return rtx | rty;
        if(val[rtx] == val[rty]) ans[u] = max(ans[u],val[rtx]);
        int mid = (l + r) >> 1;
        lson[rtx] = Merge(lson[rtx],lson[rty],l,mid,u);
        rson[rtx] = Merge(rson[rtx],rson[rty],mid + 1,r,u);
        return rtx;
    }
    void dfs(int x){
    
        for(int i = 0; i < F[a[x]].size(); i ++){
             Update(root[x],1,maxx,F[a[x]][i]);
        }
        for(int i = head[x]; i; i = Next[i]){
            int y = ver[i];
            dfs(y);
            root[x] = Merge(root[x],root[y],1,maxx,x);
        }
    }
    int main(){
        n = read();
        init(); val[0] = 0;
        for(int i = 2; i <= n; i ++){
            int x = read(); add(x,i);
        }
        for(int i = 1; i <= n; i ++) {a[i] = read();ans[i] = -1;
          maxx = max(maxx,a[i]);
        }
        maxx ++;
        dfs(1);
        for(int i = 1; i <= n; i++){
            printf("%d
    ",ans[i]);
        }
    }
    

      链接:https://codeforces.ml/contest/1407/problem/D

    手动模拟一下就能发现这就是两个单调栈;单调栈+dp

    然后不断更新值;

    #include<iostream>
    #include<cstdio>
    #include"stack"
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define inf 1e9+7
    inline int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    
    const int N = 300100, M = 200010;
    int n,a[N];
    int dp[N];
    stack<int> Q1,Q2;
    int L1[N],L2[N];
    
    int main() {
    	n = read();
    	dp[1] = 0;
    	for(int i = 1; i <= n; i ++) {a[i] = read();if(i != 1)dp[i] = dp[i - 1] + 1;}
    	for(int i = 1; i <= n; i ++){
            if(i == 1){
                Q1.push(i); Q2.push(i); continue;
            }
            while(!Q1.empty() && a[i] > a[Q1.top()]){
              // if(a[i] != a[Q1.top()])
               dp[i] = min(dp[i],dp[Q1.top()] + 1);
               Q1.pop();
            }
    
            if(Q1.size()){
                dp[i] = min(dp[i],dp[Q1.top()] + 1);
                if(a[Q1.top()] == a[i]) Q1.pop();
            }
            Q1.push(i);
    
            while(!Q2.empty() && a[i] < a[Q2.top()]){
               // if(a[i] != a[Q2.top()])
                dp[i] = min(dp[i],dp[Q2.top()] + 1);
                Q2.pop();
            }
            if(Q2.size()){
                dp[i] = min(dp[i],dp[Q2.top()] + 1);
                if(a[Q2.top()] == a[i]) Q2.pop();
            }
            Q2.push(i);
    	}
    
    	printf("%d
    ",dp[n]);
    }
    

      

  • 相关阅读:
    php入门到精通(复习笔记)
    MySQL的基础(优化)3
    php之Apache压力测试
    DOS下常用命令
    php连接MySQL分析
    php-memcached详解
    php 四种基本排序算法
    MySQL的基础(优化)2
    SQL入门之集合操作
    SQL入门之多表查询
  • 原文地址:https://www.cnblogs.com/yrz001030/p/13654357.html
Copyright © 2011-2022 走看看