The 2021 ICPC Asia Regionals Online Contest (I)部分题解

本文介绍了一道涉及图论和线段树的数据结构题目,通过对大权值和小权值的不同处理策略,实现对树形结构的有效更新与查询。文章详细展示了使用线段树进行区间更新和查询的操作细节。

C

写+调共4.5小时。吐了。最后改了一句话过了但是忘了改了哪句话了。

做法就是缩点后跑dag,纯暴力用bitset优化,加一堆分类讨论,主要还是练一下码力,没啥算法难度。

#include<bits/stdc++.h>
using namespace std ;
const int maxn = 1e5 + 10 ;
const int maxm = 10000 ;
bitset<maxm> pre_A[maxn] ;
bitset<maxm> A[maxn] ;
bitset<maxm> B[maxn] ;
bitset<maxm> ban ;
bitset<maxm> ans ;
int cnt2 ;
void cle()
{
    for(int i = 0 ; i < maxn ; i ++)
    {
        pre_A[i].reset() ;
        A[i].reset() ;
        B[i].reset() ;
    }
    ban.reset() ;
    ans.reset() ;
}
struct Tarjan
{
    int cnt , scc_num , lay ;
    vector<int> low , dfn , belong , st , s ;
    vector<bool> vis ;
    vector<vector<int>> g ;
    void init(int n)
    {
        cnt = scc_num = lay = 0 ;
        low.resize(n + 1) ;
        dfn.resize(n + 1) ;
        belong.resize(n + 1) ;
        st.resize(n + 1) ;
        s.resize(n + 1) ;
        vis.resize(n + 1) ;
        g.resize(n + 1) ;
        fill(vis.begin() , vis.end() , false) ;
        fill(low.begin() , low.end() , 0) ;
        fill(dfn.begin() , dfn.end() , 0) ;
        for(int i = 1 ; i <= n ; i ++)  g[i].clear() ;
    }
    void add(int u , int v)
    {
        g[u].push_back(v) ;
    }
    void dfs(int u)
    {
        vis[u] = true ;
        low[u] = dfn[u] = ++ lay ;
        st[++ cnt] = u ;
        for(auto v : g[u])
        {
            if(dfn[v] == 0)
            {
                dfs(v) ;
                low[u] = min(low[u] , low[v]) ;
            }
            else if(vis[v])  low[u] = min(low[u] , dfn[v]) ;
        }
        if(dfn[u] == low[u])
        {
            ++ scc_num ;
            do
            {
                belong[st[cnt]] = scc_num ;
                vis[st[cnt]] = false ;
                cnt -- ;
            } while(st[cnt + 1] != u) ;
        }
    }
    void cal(int n)
    {
        for(int i = 1 ; i <= n ; i ++)
            if(dfn[i] == 0)  dfs(i) ;
    }
    void solve()
    {
        vector<vector<int>> g2(scc_num + 1) ;
        map<pair<int , int> , int> mp ;
        vector<int> in(scc_num + 1 , 0) ;
        for(int i = 1 ; i <= cnt2 ; i ++)
        {
            for(auto v : g[i])
            {
                if(belong[v] != belong[i])
                {
                    int t1 = belong[i] ;
                    int t2 = belong[v] ;
                    assert(t1 != t2) ;
                    if(mp.count({t1 , t2}))  continue ;
                    mp[{t1 , t2}] = 1 ;
                    g2[t1].push_back(t2) ;
                    in[t2] ++ ;
                }
            }
        }
        queue<int> q ;
        for(int i = 1 ; i <= scc_num ; i ++)
            if(in[i] == 0)  
            {
                pre_A[i] = A[i] ;
                ans |= (pre_A[i] & B[i]) ;
                q.push(i) ;
            }
        while(!q.empty())
        {
            int u = q.front() ;
            q.pop() ;
            for(auto v : g
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值