jzoj5629 [NOI2018 simulation 4.4] Map (industry tumor cactus shrink ring, line segment tree merge)

Description

Rin is a very active girl.
One day Rin came to a distant city. This city has N buildings, numbered from 1 to N, of which the city center is numbered 1, the city has M two-way streets, each street is connected to two different buildings, some of the streets are connected end to end a ring. Through a long visit, Rin has already understood two characteristics of this city:
all buildings can be reached from the city center.
Any street can exist in at most one simple cycle . To Rin's delight, every building will have ramen for sale. There are many different types of ramen, but for Rin, only the degree of oiliness differs, so we consider ramen with the same degree of oil as the same type of ramen. Since the greasy level of ramen noodles in different buildings may vary, we use a positive integer to represent the greasy level of ramen noodles.
You know, ramen is Rin's favorite, but now that it's rush hour, the traffic in the city has become very congested. Rin can only pass through unblocked streets to taste the ramen in the building.
Now Rin wants to know, if she's in building number x, of the ramen Rin can taste if all the easy paths from downtown to x are blocked by the street (note the ramen that doesn't appear) is not counted):
How many types of ramen noodles have an oily degree <= y and an odd number of tastes?
How many types of ramen noodles have an even number of tastes with a greasy level <= y?
n,m 1e5

???

I looked for hours and didn't realize it was a cactus.
First, in a ring, the one that goes first from 1 is set as the top of the ring (the definition of cactus is obviously unique, and the ring where 1 is located is set to 1 as the root). Advanced shortening of cactus tree
LL: find low and dfn, dfs in the original order, for an edge (a, b), if dfn[a]<=low[b], then a is a cut point, you can Set the following point fa to a.
If dfn[a]>low[b], then b will have an upward edge. At this point a, b should be in the same ring, so fa[b]=fa[a].

It can be found that the answer to query x point is the answer to the x subtree.
Consider segment tree merging. Do it from the bottom up, and merge it into the father after completing the query at this point.
The time complexity of merging is linear with the common point of the two line segment trees.
But it is said that the total time is nlogn, the proof is unknown,
but it can be found by observing the code.
We might as well imagine that all sons are merged into the first son, and when x and y are not empty, we will continue to do so. At this time, the point y is equivalent to being discarded. The initial total number of points does not exceed nlogn, so it can be found that the number of times to go down does not exceed nlogn. Therefore, it can be considered that the time complexity is O(nlogn) (may have a larger constant, at least 2)

void merge(int &x,int y,int l,int r) {
    if (y==0) return;
    if (x==0) x=y; else {
        if (l==r) {
            int cs=T[x][1]+T[y][1];
            T[x][0]=T[x][1]=0; T[x][cs&1]=1;
            return;
        }
        merge(c[x][0],c[y][0],l,l+r>>1);
        merge(c[x][1],c[y][1],(l+r>>1)+1,r);
        update(x);
    }
}

So the complexity is O ( n l O g n )
For this question, open the weight line segment tree and save it, the odd contribution of the type x, and the even contribution. Summation when merging, pay attention to the special judgment of leaves.

Code

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int M=1.5e5+10,N=1e5+10;

int to[M*2],nex[M*2],final[N],tot,d[N];
int qy[N][2],qnex[N],qfinal[N],loc[N],qtot,ans[N];
int fa[N];

int n,m,q,a[N];
void link(int x,int y) {
    to[++tot]=y,nex[tot]=final[x],final[x]=tot;
}
int low[N],dfn[N],stm;
void form(int x) {
    low[x]=dfn[x]=++stm;
    for (int i=final[x];i;i=nex[i]) {
        int y=to[i]; if (!dfn[y]) {
            form(y);
            low[x]=min(low[x],low[y]);
        } else low[x]=min(low[x],dfn[y]);
    }
}
void build(int x) {
    for (int i=final[x]; i; i=nex[i]) {
        int y=to[i]; if (dfn[y]>dfn[x] && fa[y]==0) {
            if (dfn[x]<=low[y]) fa[y]=x,d[x]++; else fa[y]=fa[x],d[fa[x]]++;
            build(y);
        }
    }
}
int qu,Q[N],L,R,T[2700000][2],c[2700000][2],fft,root[N],mx;
void update(int x) {
    T[x][0]=T[c[x][0]][0]+T[c[x][1]][0];
    T[x][1]=T[c[x][0]][1]+T[c[x][1]][1];
}
void query(int x,int l,int r,int qw,int qloc,int &sum) {
    if (!x || l>qloc) return;
    if (r<=qloc) {
        sum+=T[x][qw];
        return;
    }
    query(c[x][0],l,l+r>>1,qw,qloc,sum);
    query(c[x][1],(l+r>>1)+1,r,qw,qloc,sum);
}

void merge(int &x,int y,int l,int r) {
    if (y==0) return;
    if (x==0) x=y; else {
        if (l==r) {
            int cs=T[x][1]+T[y][1];
            T[x][0]=T[x][1]=0; T[x][cs&1]=1;
            return;
        }
        merge(c[x][0],c[y][0],l,l+r>>1);
        merge(c[x][1],c[y][1],(l+r>>1)+1,r);
        update(x);
    }
}
void change(int &x,int l,int r,int tg) {
    if (x==0) x=++fft;
    if (l==r) {
        if (T[x][0]+T[x][1]==0) T[x][1]=1;
        else T[x][0]^=1,T[x][1]^=1;
        return;
    }
    if (tg<=(l+r>>1)) change(c[x][0],l,l+r>>1,tg);
    else change(c[x][1],(l+r>>1)+1,r,tg);
    update(x);
}

int main() {
    freopen("map.in","r",stdin);
    freopen("map.out","w",stdout);
    cin>>n>>m;
    for (int i=1; i<=n; i++) scanf("%d",&a[i]),mx=max(a[i],mx);
    for (int i=1; i<=m; i++) {
        int x,y; scanf("%d %d",&x,&y); link(x,y),link(y,x);
    }
    cin>>qu;
    for (int i=1; i<=qu; i++) {
        int ty,x,y; scanf("%d %d %d",&ty,&x,&y);
        qy[++qtot][0]=ty,qy[qtot][1]=y;
        qnex[qtot]=qfinal[x]; qfinal[x]=qtot; loc[qtot]=i;
    }
    form(1);
    build(1);
    for (int i=1; i<=n; i++) if (d[i]==0) Q[++R]=i;
    while (L<R) { 
        int x=Q[++L];
        change(root[x],1,mx,a[x]);
        for (int i=qfinal[x];i;i=qnex[i]) {
            query(root[x],1,mx,qy[i][0],qy[i][1],ans[loc[i]]);
        }
        if (fa[x]) merge(root[fa[x]],root[x],1,mx);
        if (x && --d[fa[x]]==0) Q[++R]=fa[x];
    }
    for (int i=1; i<=qu; i++) printf("%d\n",ans[i]);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325362205&siteId=291194637