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;
}
2:Select Edges 这道题是一道树形DP+贪心的题目,题目意思:给定一棵树,每条边有一个边权值w,每个点有周边边个数限制,选一个边集,使得每个点相邻的边在这个集合里的个数不超过限制,并且要最大化边数权值之和 dp[i][j]j为0/1表示节点i的子树中是否要选当前点到其父亲节点的边那么dp转移方程为

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;
}
posted @ 2024-09-19 21:52  Kevinhwbb  阅读(6)  评论(0编辑  收藏  举报