2024.11.12
今日总结:
1:http://www.nfls.com.cn:10611/p/P862
这道题主要是考察树上差分和lca,学习了树上差分,这道题也可用用dfs+bfs+lca来解决
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int n,Min;
int d[N],f[N][30],c1[N],c2[N],num[N],ans[N];
struct Node
{
vector<int> nxt,nxt_v1,nxt_v2;
}Node[N];
void bfs(int v)
{
queue<int> q;
d[v] = 1;
q.push(v);
int t = (int)(log(n) / log(2)) + 1;
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = 0;i < Node[u].nxt.size();i ++)
{
int y = Node[u].nxt[i];
if(d[y] != 0) continue;
d[y] = d[u] + 1;
f[y][0] = u;
int v1 = Node[u].nxt_v1[i],v2 = Node[u].nxt_v2[i];
c1[y] = v1,c2[y] = v2;
for(int j = 1;j <= t;j ++)
f[y][j] = f[f[y][j - 1]][j - 1];
q.push(y);
}
}
}
int LCA(int x,int y)
{
int t = (int)(log(n) / log(2)) + 1;
if(d[x] > d[y]) swap(x,y);
for(int i = t;i >= 0;i--)
if(d[f[y][i]] >= d[x]) y = f[y][i];
if(x == y) return x;
for(int i = t;i >= 0;i --)
if(f[y][i] != f[x][i]) y = f[y][i],x = f[x][i];
return f[x][0];
}
int dfs(int now,int fa)
{
ans[now] += num[now];
for(int i = 0;i < Node[now].nxt.size();i ++)
{
int y = Node[now].nxt[i];
if(fa != y) ans[now] += dfs(y,now);
}
return ans[now];
}
signed main()
{
freopen("coffee.in","r",stdin);
freopen("coffee.out","w",stdout);
scanf("%lld",&n);
for(int i = 1;i <= n - 1;i ++)
{
int u,v,v1,v2;
scanf("%lld%lld%lld%lld",&u,&v,&v1,&v2);
Node[u].nxt.push_back(v),Node[v].nxt.push_back(u);
Node[u].nxt_v1.push_back(v1),Node[v].nxt_v1.push_back(v1);
Node[v].nxt_v2.push_back(v2),Node[u].nxt_v2.push_back(v2);
}
bfs(1);
for(int i = 2;i <= n;i ++)
{
int u = i - 1,v = i,z = LCA(u,v);
num[u] += 1,num[v] += 1,num[z] -= 2;
}
dfs(1,-1);
for(int i = 2;i <= n;i ++)
{
int v1 = c1[i],v2 = c2[i],t = ans[i];
Min += min(v1 * t,v2);
}
printf("%lld\n",Min);
return 0;
}
2:http://www.nfls.com.cn:10611/p/P592
这道题主要是一道图论的题,可以用优先队列优化
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n,m,startx,starty,endx,endy;
int st[N][N],north[N][N],south[N][N],east[N][N],west[N][N];
int dx[5] = {-1,1,0,0},dy[5] = {0,0,1,-1};
string s[N];
struct Node
{
int x,y,dis;
bool operator<(const Node &a)const{return dis > a.dis;}
};
priority_queue<Node> pq;
int main()
{
freopen("portals.in","r",stdin);
freopen("portals.out","w",stdout);
scanf("%d%d",&n,&m);
memset(st,0x3f,sizeof(st));
for(int i = 1;i <= n;i ++)
{
cin >> s[i];
s[i] = '#' + s[i] + '#';
for(int j = 1;j <= m;j ++)
{
if(s[i][j] == 'S') startx = i,starty = j;
if(s[i][j] == 'C') endx = i,endy = j;
}
}
// if(startx == endx && starty == endy)
// {
// printf("0\n");
// return 0;
// }
for(int i = 0;i <= m + 1;i ++)
s[0] += '#',s[n + 1] += '#';
for(int i = 1;i <= m;i ++)
for(int j = 1;j <= n;j ++)
if(s[j][i] != '#') north[j][i] = north[j - 1][i] + 1;
for(int i = 1;i <= m;i ++)
for(int j = n;j >= 1;j --)
if(s[j][i] != '#') south[j][i] = south[j + 1][i] + 1;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++)
if(s[i][j] != '#') east[i][j] = east[i][j - 1] + 1;
for(int i = 1;i <= n;i ++)
for(int j = m;j >= 1;j --)
if(s[i][j] != '#') west[i][j] = west[i][j + 1] + 1;
pq.push(Node{startx,starty,0});
st[startx][starty] = 0;
while(pq.size())
{
Node t = pq.top();
pq.pop();
for(int i = 0;i < 4;i ++)
{
int zx = t.x + dx[i],zy = t.y + dy[i];
if(zx >= 1 && zx <= n && zy >= 1 && zy <= m && s[zx][zy] != '#' && st[t.x][t.y] + 1 < st[zx][zy])
{
st[zx][zy] = st[t.x][t.y] + 1;
pq.push(Node{zx,zy,st[zx][zy]});
}
}
int val = min({north[t.x][t.y],south[t.x][t.y],east[t.x][t.y],west[t.x][t.y]}) - 1;
int door_n = t.x - north[t.x][t.y] + 1,door_s = t.x + south[t.x][t.y] - 1,door_e = t.y - east[t.x][t.y] + 1,door_w = t.y + west[t.x][t.y] - 1;
if(st[t.x][t.y] + val + 1 < st[door_n][t.y])
{
st[door_n][t.y] = st[t.x][t.y] + val + 1;
pq.push(Node{door_n,t.y,st[door_n][t.y]});
}
if(st[t.x][t.y] + val + 1 < st[door_s][t.y])
{
st[door_s][t.y] = st[t.x][t.y] + val + 1;
pq.push(Node{door_s,t.y,st[door_s][t.y]});
}
if(st[t.x][t.y] + val + 1 < st[t.x][door_e])
{
st[t.x][door_e] = st[t.x][t.y] + val + 1;
pq.push(Node{t.x,door_e,st[t.x][door_e]});
}
if(st[t.x][t.y] + val + 1 < st[t.x][door_w])
{
st[t.x][door_w] = st[t.x][t.y] + val + 1;
pq.push(Node{t.x,door_w,st[t.x][door_w]});
}
}
printf("%d\n",st[endx][endy]);
return 0;
}
3:https://www.luogu.com.cn/problem/P3537
这道题是一道背包的题目,但题目非常新颖,一定要考虑边界问题
点击查看代码
//dp[k]表示,在满足a <= m的物品中c属性之和为k的方案中最小的b属性的最大值
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
const int M = 1e6 + 10;
int n,q;
int dp[M];
bool ans[M];
struct Node1
{
int a,b,c;
bool operator<(const Node1 &x)const {return a < x.a;}
}a[N];
struct Node2
{
int m,k,s,id;
bool operator<(const Node2 &x)const{return m < x.m;}
}b[M];
int main()
{
// freopen("Cloakroom.in","r",stdin);
// freopen("Cloakroom.out","w",stdout);
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
scanf("%d%d%d",&a[i].c,&a[i].a,&a[i].b);
scanf("%d",&q);
for(int i = 1;i <= q;i ++)
scanf("%d%d%d",&b[i].m,&b[i].k,&b[i].s),b[i].id = i;
sort(a + 1,a + n + 1);
sort(b + 1,b + q + 1);
dp[0] = 1 << 30;
for(int i = 1,j = 1;i <= q;i ++)
{
for(;j <= n && a[j].a <= b[i].m;j ++)
for(int k = 1e5;k >= a[j].c;k --)
dp[k] = max(dp[k],min(dp[k - a[j].c],a[j].b));
if(dp[b[i].k] > b[i].m + b[i].s) ans[b[i].id] = 1;
}
for(int i = 1;i <= q;i ++)
puts(ans[i] ? "TAK" : "NIE");
return 0;
}
4:http://www.nfls.com.cn:20035/contest/2090/problem/4#submit_code
这道题是一道状压DP,Dp的定义以后可以设为持续时间状态,状压基本思路
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n,l;
int val[N],num[N][N],dp[1 << 21];
int main()
{
scanf("%d%d",&n,&l);
for(int i = 0;i < n;i ++)
{
scanf("%d%d",&val[i],&num[i][0]);
for(int j = 1;j <= num[i][0];j ++)
scanf("%d",&num[i][j]);
}
int ans = 0x3f3f3f3f;
memset(dp,-1,sizeof(dp));
dp[0] = 0;
for(int t = 0;t < (1 << n);t ++)
{
if(dp[t] == -1) continue;
for(int i = 0;i < n;i ++)
{
if((t >> i) & 1) continue;
int *p = upper_bound(num[i] + 1,num[i] + num[i][0] + 1,dp[t]) - 1;
if(p != num[i]) dp[t|(1 << i)] = max(dp[t|(1 << i)],num[i][p - num[i]] + val[i]);
else dp[t|(1 << i)] = dp[t];
}
if(dp[t] >= l) ans = min(ans,__builtin_popcount(t));
}
if(ans == 0x3f3f3f3f) puts("-1");
else printf("%d\n",ans);
return 0;
}