列表

详情


NC20543. [HAOI2016]地图

描述

一天rin来到了一个遥远的都市。这个都市有n个建筑,编号从1到n,其中市中心编号为1,这个都市有m条双向通行的街道,每条街道连接着两个建筑,其中某些街道首尾相连连接成了一个环。rin通过长时间的走访,已经清楚了这个都市的两个特点:
1. 从市中心出发可以到达所有的建筑物。
2. 任意一条街道最多存在与一个简单环中。令
rin心花怒放的是,每个建筑物都会有拉面售卖。拉面有很多不同的种类,但对于rin而言只有油腻程度的不同,因此我们把油腻程度相同的拉面看做同一种拉面。由于不同建筑物的拉面的油腻程度可能不同,我们用一个正整数来表示拉面的油腻程度。要知道,拉面可是rin的最爱,但是现在到了下班高峰期,都市的交通变得非常的堵塞。 rin只能通过没有被堵死的街道通行,去品尝所在建筑物的拉面。现在rin想知道,如果她正在编号为x的建筑物,那么在从市中心到x的所有简单路径经过的街道都被堵死的情况下,rin可以品尝到的拉面中(注意没有出现的拉面是不能算在里面的):
1. 油腻程度≤ y且品尝次数为奇数次的拉面有多少种?
2. 油腻程度≤ y且品尝次数为偶数次的拉面有多少种?

输入描述

第一行两个正整数n,m,含义如题所示第二行一共N个正整数,第i个数Ai表示第i个建筑物出售的拉面的油腻程度。 
接下来M行,每行两个正整数x,y,表示在建筑物x,y之间有一条双向通行的街道。数据保证1 ≤ x < y ≤ N
接下来一行一个正整数Q,表示询问个数。
接下来Q行每行三个非负整数ty,x,y,x表示询问的建筑物编号,y表示油腻程度的限制,ty=0时表示询问偶数,ty=1表示询问奇数。
N ≤ 100000,M ≤ 150000,Q ≤ 100000,Ai ≤ 10^6
提示:请注意数据范围中的≤,特殊条件中提到的??均为询问中的y,对于所有的数据,有y ≤ 10^6

输出描述

一共Q行,对于每个询问输出一个答案。

示例1

输入:

10 12
1 10 4 5 2 10 1 8 4 8 
1 2
1 3
1 4
2 5
4 6
4 7
7 8
2 9
8 10
1 6
8 10
4 7
10
0 3 9
1 7 6
0 5 2
1 10 9
0 5 7
1 7 4
0 7 3
1 2 7
0 3 4
0 3 8

输出:

0
1
0
1
0
1
0
2
0
0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 449ms, 内存消耗: 92520K, 提交时间: 2020-05-22 13:41:53

#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;
}

C++11(clang++ 3.9) 解法, 执行用时: 239ms, 内存消耗: 16380K, 提交时间: 2019-03-16 13:45:06

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 150100
#define M 1000001
#define S 1000
#define P 320

using namespace std;

int to[N*2],fir[N],nex[N*2],T,dfn[N],ord[N],num[M],s[2][S+5],own[N];
int n,m,p,ans[N],top=1,cnt,fa[N],til[N],val[N],las[N],sta[N];
bool bz[N],vis[N];
struct qry{int x,y,s,v,p;}q[N];
bool cmp(qry a,qry b){return own[a.x]<own[b.x] || (own[a.x]==own[b.x] && a.y<b.y);}

void link(int x,int y){
    to[++top]=y;nex[top]=fir[x];fir[x]=top;
}

void dg(int w,int dad){
    if(vis[w]){
        for(int i=top;sta[i]!=w;i--)fa[sta[i]]=w;
        return;
    }
    vis[sta[++top]=w]=1;las[w]=dad;
    for(int i=fir[w];i;i=nex[i])if(!bz[i/2]){
        bz[i/2]=1;dg(to[i],w);
    }--top;
}
void dfs(int w){
    ord[dfn[w]=++cnt]=w;til[w]=dfn[w];
    for(int i=fir[w];i;i=nex[i])dfs(to[i]),til[w]=max(til[w],til[to[i]]);
}

void put(int v){
    num[v]++;int k=(v-1)/S+1,p=num[v]&1;
    s[1][k]+=p*2-1;if(num[v]>1)s[0][k]+=1-2*p;
}
void take(int v){
    num[v]--;int k=(v-1)/S+1,p=num[v]&1;
    s[1][k]+=p*2-1;if(num[v])s[0][k]+=1-2*p;
}
int query(int tp,int v){
    int r=0,p,i;
    for(i=1,p=S;p<v;i++,p+=S)r+=s[tp][i];
    for(p-=S-1;p<=v;p++)r+=(num[p])&&(num[p]%2==tp);
    return r;
}

int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&val[i]),own[i]=(i-1)/P+1;
    for(int i=1;i<=m;i++){
        int x,y;scanf("%d %d",&x,&y);link(x,y);link(y,x);
    }top=0;dg(1,0);top=0;
    for(int i=1;i<=n;i++)if(!fa[i])fa[i]=las[i];
    for(int i=1;i<=n;i++)fir[i]=0;
    for(int i=2;i<=n;i++)link(fa[i],i);
    dfs(1);scanf("%d",&p);
    for(int i=1;i<=p;i++){
        int x,s,v;scanf("%d %d %d",&s,&x,&v);
        q[i]=(qry){dfn[x],til[x],s,v,i};
    }sort(q+1,q+p+1,cmp);
    for(int i=1,l=1,r=0;i<=p;i++){
        int x=q[i].x,y=q[i].y,v=q[i].v,s=q[i].s;
        while(x<l)put(val[ord[--l]]);while(y>r)put(val[ord[++r]]);
        while(x>l)take(val[ord[l++]]);while(y<r)take(val[ord[r--]]);
        ans[q[i].p]=query(s,v);
    }
    for(int i=1;i<=p;i++)printf("%d\n",ans[i]);
}

上一题