题解
链接: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]);
}
浙公网安备 33010602011771号