题解

链接: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\n");
	else
		printf("%d\n", 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("\n");
#define Debug printf("this_ok\n");
#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\n",a);
#define print_int(a,b) if(b == 0) printf("%d ",a); else printf("%d\n",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\n",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\n");
    else {
        printf("%d\n",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\n", 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("\n");
#define Debug printf("this_ok\n");
#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\n",a);
#define print_int(a,b) if(b == 0) printf("%d ",a); else printf("%d\n",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\n",len);
        for(int i = 1;i <= len; i ++){
           int x = query(root,1,len,i);
         //  printf("x = %d b[i] = %d\n",x,b[i]);
           if(x >= 1 && x <= n)
           Q.insert(x);
        }
        printf("%d\n",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\n",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\n",dp[n]);
}

  

posted @ 2020-09-11 21:18  风生  阅读(113)  评论(0编辑  收藏  举报