191101T3层层回忆(fsy)代码分析

20191101T3层层回忆

子树问题

  1. 直接在树上操作
  2. in[] , out[] 打平整棵树。

抽象题目

抽象为二维偏序。
这里只分析前缀。, 求。
询问离线,对每一个询问建vector,N个dfn的询问就是vector[],按照询问顺序添加数据(排序,第一维)。在树状数组里面求sz下标的前缀(第二维)的BitOr值(答案在树状数组查询的值里)。

loboqui

#include
using namespace std;

struct fastio
{
    fastio&operator-(int&a)
    {
        a=0; int n=0; char c=getchar();
        while(c<'0'||c>'9') c=='-'&&(n=1), c=getchar();
        while(c>='0'&&c<='9') a=a*10+(c&15), c=getchar();
        n&&(a=-a); return *this;
    }
}ri;

const int N = 4e5+5, M = 3e6+5;
int m;
struct
{
    int a[M];
    void clr()
    {
        memset(this, 0, sizeof *this);
    }
    void add(int x, int y)
    {
        for(; x<=m; x+=x&-x) a[x]|=y;
    }
    int query(int x)
    {
        int ans = 0;
        for(; x; x-=x&-x) ans|=a[x];
        return ans;
    }
}bit;
int f[N];
int nxt[N<<1], fst[N<<1], to[N<<1];
void aE(int u, int v)
{
    static int i=1;
    nxt[++i] =fst[u]; fst[u]=i; to[i]=v;
}
int in[N], out[N], uid[N];
void dfs(int u, int fa)
{
    static int clk;
    in[u] = ++clk; uid[clk] = u;
    for(int e=fst[u];e;e=nxt[e])
    {
        int v = to[e];
        if(v^fa) dfs(v, u), f[u]+=f[v];
    }
    out[u]=clk; m=max(m, f[u]);
}
int n,q;
vector pre[N], suf[N];
int ans[N];

int main()
{
/////////   freopen("forever.in", "r", stdin);
    ri-n-q;
    int x,y;
    for(int i=1; i^n; i++)
    {
        ri-x-y; aE(x,y); aE(y,x);
    }
    for(int i=1; i<=n; i++) ri-f[i];
    dfs(1, 0);
    for(int i=1; i<=n; i++)
    {
        if(in[i]>1) pre[in[i]-1].push_back(i);
        if(out[i]

fsy

#include
#define cs const
using namespace std;
cs int N = 4e5 + 5, M = 1e6 + 5;
int read(){
    int cnt = 0, f = 1; char ch = 0;
    while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
    while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
    return cnt * f;
}
int first[N], nxt[N << 1], to[N << 1], tot;
void add(int x, int y){
    nxt[++tot] = first[x], first[x] = tot, to[tot] = y;
}
int n, Cap, Mx;
int a[N], ans[N]; // a - f -sz
int in[N], out[N], ps[N], sign; //ps: dfn -> uid
void dfs(int u, int fa){
    in[u] = ++sign; ps[sign] = u;
    for(int i = first[u]; i; i = nxt[i]){
        int t = to[i]; if(t == fa) continue;
        dfs(t, u); a[u] += a[t];
    } out[u] = sign; Mx = max(Mx, a[u]); //a good clk
}
struct BIT{
    int c[M];
    void clear(){ memset(c, 0, sizeof(c)); }
    void add(int x, int v){ for(;x<=Mx; x+=x&-x) c[x] |= v; }
    int ask(int x){ int ans = 0; for(;x;x-=x&-x) ans |= c[x]; return ans; }
}bit;
vector pre[N], suf[N];
// 前缀后缀分别做一遍  
int calc(int x){
    if(in[x] > 1) pre[in[x] - 1].push_back(x); //前缀查询  //pre[q] 询问位置为q的前缀询问 的答案 发送给内容 x 
    if(out[x] < n) suf[out[x] + 1].push_back(x); //后缀查询     
}
int main(){
    n = read(), Cap = read(); //capital
    for(int i = 1; i < n; i++){
        int x = read(), y = read();
        add(x, y); add(y, x);
    } 
    for(int i = 1; i <= n; i++) a[i] = read();
    dfs(Cap, 0); // deal sz , f
    for(int i = 1; i <= n; i++) calc(i); // 询问离线  
    for(int i = 1; i <= n; i++){  // a - f -sz
        bit.add(a[ps[i]], a[ps[i]]); //ps: dfn -> uid
        for(int j = 0; j < pre[i].size(); j++){
            int nx = pre[i][j];
            ans[nx] |= bit.ask(a[nx] - 1);
        }
    } bit.clear();
    for(int i = n; i >= 1; i--){
        bit.add(a[ps[i]], a[ps[i]]);
        for(int j = 0; j < suf[i].size(); j++){
            int nx = suf[i][j];
            ans[nx] |= bit.ask(a[nx] - 1);
        }
    }
    for(int i = 1; i <= n; i++) cout << ans[i] << " ";
    return 0;
}

你可能感兴趣的:(191101T3层层回忆(fsy)代码分析)