洛谷P3180 [HAOI2016]地图

链接

点击跳转

题解

建立圆方树之后,原问题转化为:

询问一个区间里面有多少种值出现了奇数次/偶数次?

有一个经典问题就是询问区间有多少种不同的值,这个可以莫队解决

那这个题其实就几乎一样,直接莫队做就行了

另一种可能的做法

直接 d s u   o n   t r e e dsu\ on\ tree 好像就结束了,但是应该代码也不会比我的做法短多少

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct Graph
{
    int etot, head[maxn], to[maxe], next[maxe], w[maxe];
    void clear(int N)
    {
        for(int i=1;i<=N;i++)head[i]=0;
        etot=0;
    }
    void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
    #define forp(_,__) for(auto p=__.head[_];p;p=__.next[p])
}G;
struct Circle_Square_Tree
{
    ll dfn[maxn], low[maxn], tim, tot, s[maxn], e[maxn], n;
    vector<ll> cir[maxn], w[maxn];
    Graph T;
    void dfs(Graph &G, ll u, ll fa)
    {
        ll ch=0;
        s[++*s]=u;
        dfn[u]=low[u]=++tim;
        forp(u,G)
        {
            auto v=G.to[p];
            if(!dfn[v])
            {
                ch++;
                e[v]=p;
                dfs(G,v,u);
                low[u]=min(low[u],low[v]);
                if(low[v]==dfn[u])
                {
                    if(s[*s]==v)
                    {
                        ll W;
                        forp(u,G)if(G.to[p]==s[*s])W=G.w[p];
                        T.adde(v,u,W);
                        T.adde(u,v,W);
                        --*s;
                    }
                    else
                    {
                        tot++;
                        forp(u,G)
                            if(G.to[p]==s[*s])
                                w[tot].emb(G.w[p]);
                        for(ll x=0;x!=v;--*s)
                        {
                            x=s[*s];
                            cir[tot].emb(x);
                            ll bk=w[tot].back();
                            w[tot].emb(bk+G.w[e[x]]);
                        }
                        cir[tot].emb(u);
                        ll i; rep(i,0,cir[tot].size()-1)
                        {
                            ll W=min((ll)w[tot].at(i),w[tot].back()-w[tot].at(i));
                            T.adde(n+tot,cir[tot].at(i),W);
                            T.adde(cir[tot].at(i),n+tot,W);
                        }
                    }
                }
            }
            else low[u]=min(low[u],dfn[v]);
        }
    }
    void build(Graph &G, ll N)
    {
        ll i;
        for(i=1;i<=N;i++)dfn[i]=low[i]=0;
        T.clear(N*2);
        *s=tim=tot=0;
        n=N;
        for(i=1;i<=N;i++)if(!dfn[i])dfs(G,i,-1);
    }
}cstree;
struct BIT
{
    ll bit[maxn], n;
    void init(int N){n=N;for(int i=1;i<=n;i++)bit[i]=0;}
    ll lowbit(ll x){return x&(-x);}
    void add(ll pos, ll v)
    {
        for(;pos<=n;pos+=lowbit(pos))bit[pos]+=v;
    }
    ll sum(ll pos)
    {
        ll ans(0);
        for(;pos;pos-=lowbit(pos))ans+=bit[pos];
        return ans;
    }
}bit[2];
struct Easy_Tree
{
    int depth[maxn], dist[maxn], tid[maxn], rtid[maxn], tim, size[maxn], rev[maxn];
    void dfs(int pos, int pre, Graph& G)
    {
        tid[pos]=++tim;
        rev[tid[pos]]=pos;
        size[pos]=1;
        forp(pos,G)if(G.to[p]!=pre)
        {
            depth[G.to[p]]=depth[pos]+1;
            dist[G.to[p]]=dist[pos]+G.w[p];
            dfs(G.to[p],pos,G);
            size[pos]+=size[G.to[p]];
        }
        rtid[pos]=tim;
    }
    void run(Graph& G, int root)
    {
        tim=0;
        depth[root]=1;
        dfs(1,0,G);
    }
}et;
ll cnt[maxn], a[maxn], id[maxn], y[maxn], type[maxn], l[maxn], r[maxn], ans[maxn];
void upd(ll x, ll opt)
{
    x=a[et.rev[x]];
    if(x==0)return;
    if(cnt[x])bit[cnt[x]&1].add(x,-1);
    cnt[x]+=opt;
    if(cnt[x])bit[cnt[x]&1].add(x,+1);
}
int main()
{
    ll i, n, q, u, v, m, L, R;
    n=read(), m=read();
    rep(i,1,n)a[i]=read();
    rep(i,1,m)
    {
        u=read(), v=read();
        G.adde(u,v), G.adde(v,u);
    }
    cstree.build(G,n);
    et.run(cstree.T,1);
    q=read();
    rep(i,1,q)
    {
        type[i]=read();
        ll x=read();
        l[i]=et.tid[x];
        r[i]=et.rtid[x];
        y[i]=read();
        id[i]=i;
    }
    ll S=sqrt(1e5);
    sort(id+1,id+q+1,[&](ll a, ll b){return l[a]/S==l[b]/S ? r[a]<r[b] : l[a]/S<l[b]/S; });
    bit[0].init(1e6), bit[1].init(1e6);
    L=1, R=0;
    rep(i,1,q)
    {
        for(;L>l[id[i]];L--)upd(L-1,+1);
        for(;R<r[id[i]];R++)upd(R+1,+1);
        for(;L<l[id[i]];L++)upd(L,-1);
        for(;R>r[id[i]];R--)upd(R,-1);
        ans[id[i]]=bit[type[id[i]]].sum(y[id[i]]);
    }
    rep(i,1,q)
    {
        printf("%lld\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/106278155