2024.9.19
今日总结:
1:Well-defined Path Queries on a Namori
这道题是要询问(A,B)是否存在从A到B的路径,且只有一条,那么解决方法只需要用两遍dfs一个是用来查询是否有道路,第二个用来查询是否只有唯一路
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n,Q,cnt;
int point[N],now_point[N];
bool flag = 0;
bool vis[N],find_point[N];
vector<int> vec[N];
inline void dfs(int now,int lst)
{
if(flag) return;
point[++ cnt] = now;
vis[now] = 1;
for(auto i : vec[now])
{
if(vis[i] && i != lst)
{
for(int j = 1;j <= cnt;j ++)
{
if(point[j] == i)
{
for(int k = j;k <= cnt;k ++)
find_point[point[k]] = 1;
flag = 1;
}
}
return;
}
if(!vis[i]) dfs(i,now);
}
cnt --;
}
inline void dfs1(int now,int ans)
{
vis[now] = 1;
now_point[now] = ans;
for(auto i : vec[now])
if(!find_point[i] && !vis[i]) dfs1(i,ans);
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
int u,v;
scanf("%d %d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
dfs(1,0);
memset(vis,0,sizeof(vis));
memset(now_point,0,sizeof(now_point));
for(int i = 1;i <= n;i ++)
if(find_point[i]) dfs1(i,i);
scanf("%d",&Q);
while(Q --)
{
int x,y;
scanf("%d %d",&x,&y);
if(now_point[x] == now_point[y]) printf("Yes\n");
else printf("No\n");
}
return 0;
}
dp[v][0] = dp[v][1] + w[now][v]
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> PII;
const int N = 3e5 + 10;
const int INF = 1e18;
int n;
int limit[N],dp[N][2];
vector<PII> vec[N];
vector<int> cev;
inline int max(int a,int b)
{
if(a > b) return a;
else return b;
}
inline void dfs(int now,int fa)
{
int res = 0;
for(auto [v,w] : vec[now])
if(v != fa) dfs(v,now);
cev.clear();
for(auto [v,w] : vec[now])
if(v != fa)
{
res += dp[v][0];
cev.push_back(dp[v][1] + w - dp[v][0]);
}
sort(cev.begin(),cev.end());
reverse(cev.begin(),cev.end());
if(limit[now] == 0)
{
dp[now][0] = res;
dp[now][1] = -INF;
}
else
{
dp[now][0] = dp[now][1] = res;
int len = cev.size();
for(int i = 0;i < len;i ++)
{
if(cev[i] < 0) break;
if(i < limit[now]) dp[now][0] += cev[i];
if(i < limit[now] - 1) dp[now][1] += cev[i];
}
}
}
signed main()
{
scanf("%lld",&n);
for(int i = 1;i <= n;i ++)
scanf("%lld",&limit[i]);
for(int i = 1;i < n;i ++)
{
int u,v,w;
scanf("%lld %lld %lld",&u,&v,&w);
vec[u].push_back(make_pair(v,w));
vec[v].push_back(make_pair(u,w));
}
dfs(1,1);
int Max = max(dp[1][1],dp[1][0]);
printf("%lld\n",Max);
return 0;
}
3:Operations on a Matrix
本题可以直接用树状数组解决,针对第一个要求需要进行调整,其余两个与模板相同。那么主要解决第一个问题如何将更改区间列的每一个数
记录从开始到该次操作的所有第一个操作列增加值为ch1,从开始到最后一次操作2的列增加值记作ch2,答案为x+ch2-ch1
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int n,m,Q;
int tr[N],ans[N],lst[N];
vector<int> g[N];
struct node{
int ok,x,y,z;
}q[N];
inline int lowbit(int x)
{
return x & (-x);
}
inline void add(int i,int x)
{
while(i <= m)
{
tr[i] += x;
i += lowbit(i);
}
}
inline int query(int x)
{
int res = 0;
while(x)
{
res += tr[x];
x -= lowbit(x);
}
return res;
}
signed main()
{
scanf("%lld %lld %lld",&n,&m,&Q);
for(int i = 1;i <= Q;i ++)
{
scanf("%lld %lld %lld",&q[i].ok,&q[i].x,&q[i].y);
if(q[i].ok == 1) scanf("%lld",&q[i].z);
if(q[i].ok == 2) lst[q[i].x] = i;
if(q[i].ok == 3) g[lst[q[i].x]].push_back(i);
}
for(int i = 1;i <= Q;i ++)
{
if(q[i].ok == 1) add(q[i].x,q[i].z),add(q[i].y + 1,-q[i].z);
if(q[i].ok == 2)
for(int j = 0;j < g[i].size();j ++)
ans[g[i][j]] += q[i].y - query(q[g[i][j]].y);
if(q[i].ok == 3) printf("%lld\n",ans[i] + query(q[i].y));
}
return 0;
}