財神娛樂首存即享優惠回饋唷~詳情請進👉

[JZOJ60九州娛樂城評價89]【CodeChef 2014 April Challenge】Final Battle of C

Description

\(n,q,V\leq 100000,w_i\leq 10^9\)

Solution

又是一道大數據布局

因為有一個下取整,這就致使了不同時間的點竄值是不克不及簡略的間接加在一路的。

輕易發明,1操作的影響只會影響到間隔不跨六合彩版路越log的點。

如許咱們很輕易失去一個\(q\log n\log ^2V\)的做法

統一深度的點竄有一種套路是維護BFS序。
關于子樹內的點,咱們將log個深度對應的BFS序區間減往響應的影響。

關于點竄點的log個有效的先人,咱們也相似操作,注重反復影響的要減往。

如許咱們每次點竄要點竄\(log^2V\)段區間,用線段樹維護又有一個log
因為每個點只會變負一次,咱們只要要維護區間減得同時維護區間最小值,發明區間區間最小值變非正了就暴力走上來改,更新謎底,如許每個點只會改一次,龐大度是有保障的。

固然如許已經經能經由過程這道題了(我怎么會說這跑的比log^2還快)
咱們還要探求更良好的算法。

咱們無妨先不點竄子樹,每次點竄點只改先人。記載\(tag_{i,j}\)透露表現點i對間隔本人為\(j\)的兒子的影響

那末每次點竄就釀成了\(log^2\)的了,咱們只要要對它的log的先人,每一個改一下標志。
目前可以支撐單點查問是否變非正,間接跳log級先人查一下就好。

但咱們要求某個時間的子樹內非誤點的個數,若是咱們能疾速算出每個點變非正的時間就好了。

可以團體二分/CDQ分治!

咱們關于一切的操作按時間分治,關于分治區間\([l,r]\)記一個點集S,透露表現S中的點在時間[l,r]變非正,咱們將浮現時間在mid之前的一切操作都處置,一個個查問S中的點是否變非正,望是下放左區間仍是右區間。

闡發龐大度,每個點會查問log次,每次查問跳log個先人,兩個log
每個操作會用log次,每次時間log^2,這弗成取!

咱們發明若是每次都把操作暴力插歸撤消,這特別很是的鋪張。
由于咱們總的必要查問的\(tag_{i,j}\)的改變次數只有$n\log^2 $

咱們可以將\(tag\)數組可持久化,用一個鏈表或者者vector存下每次改變的時間,查問的時辰只要要移一下指針即可,輕易望出指針的挪移總次數只有\(n\log ^2\)

那末總的時間龐大度就降到了\(O(Q\log^2)\)

Code

//why always data structures ????
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,b) for(int i=a;i>=b;--i)
#define N 100005
#define LL long long
using namespace std;
int fs[N],nt[2*N],dt[2*N],pr[N],n,m,w[N],dfw[N],sz[N],dfn[N],ans[N],m1,ask[N][3],f[N],dep[N];
LL sm[N];


//tree_array
int c[N];
int lowbit(int k)
{
    return k&-k;
}
int get(int k)
{
    int s=0;
    while(k) s+=c[k],k-=lowbit(k);
    return s; 
}
void put(int k)
{
    while(k<=n) c[k]++,k+=lowbit(k);
}

//prepare
void link(int x,int y)
{   
    nt[++m1]=fs[x];
    dt[fs[x]=m1]=y;
}
void dfs(int k,int fa)
{
    f[k]=fa;
    dfw[dfn[k]=++dfn[0]]=k;
    dep[k]=dep[fa]+1;
    sz[k]=1;
    for(int i=fs[k];i;i=nt[i]) 
    {
        int p=dt[i];
        if(p!=fa) dfs(p,k),sz[k]+=sz[p];
    }
}

//solve

struct node
{
    LL v,t;     
}; 
vector<node> tag[N][32];
int le[N][32],now[N][32],d[N],u1[N],u2[N],ts[N];

void ins(int k,int s,int ti)
{
    if(!s||!k) return;
    int v=s;
    for(int c=0;v;c++) 
    {
        int vl=(f[k])539連碰意思?v-(v>>2):v;
        if(le[k][c]==0) tag[k][c].push_back((node){vl,ti});
        else tag[k][c].push_back((node){vl+tag[k][c][le[k][c]-1].v,ti});
        le[k][c]++;
        v>>=1;
    }
    ins(f[k],s>>1,ti);
}

LL query(int k,int ti)
{
    LL s=0;
   捕魚達人外掛 for(int p=0;p<=31&&k;k=f[k],p++)
    {
        while(now[k][p]<le[k][p]-1&&tag[k][p][now[k][p]+1].t<=ti) now[k][p]++;
        wh地下539坐車ile(now[k][p]>0&&tag[k][p][now[k][p]].t>ti) now[k][p]--;
        if(now[k][p]<le[k][p]&&tag[k][p][now[k][p]].t<=ti) s+=tag[k][p][now[k][p]].v;
    } 
    return s;
}
void doit(int l,int r,int x,int y)
{
    if(x>y) return;
    if(l==r) {fo(i,x,y) ts[d[i]]=l;return;}
    int mid=(l+r)>>1;
    u1[0]=0,u2[0]=0;
    fo(i,y)
    {
        if(pr[d[i]]<=query(d[i],mid)) u1[++u1[0]]=d[i];
        else u2[++u2[0]]=d[i];
    }
    fo(j,1,u1[0]) d[x+j-1]=u1[j];
    fo(j,u2[0]) d[x+u1[0]+j-1]=u2[j];
    int md=x+u1[0]-1;
    doit(l,mid,md);
  大樂透開獎號碼  doit(mid+1,r,md+1,y);
}

bool cmp(int x,int y)
{
    return ts[x]<ts[y];
}
int main()
{
    cin>>n;
    fo(i,n) scanf(公眾%d"大眾,&pr[i]);
    
    fo(i,n-1)
    {
        int x,y;
        scanf("大眾%d%d公眾,&x,&y);
        link(x,y),link(y,x);
    }
    dfs(1,0);

    int q;
    cin>>q;
    fo(i,q) 
    {
        scanf(公眾%d%d公眾,&ask[i][0],&ask[i][1]);
        if(ask[i][0]==1) 
        {
            scanf("大眾%d"大眾,&ask[i][2]);
            ins(ask[i][1],ask[i][2],i);
        }
    }
    fo(i,n) d[i]=i;
    doit(1,q+1,n);

    sort(d+1,d+n+1,cmp);
    for(int i=1,j=1;i<=q;i++)
    {
        while(j<=n&&ts[d[j]]<=i) put(dfn[d[j]]),j++;
        if(ask[i][0]==2) printf("大眾%d\n"大眾,get(dfn[ask[i][1]]+sz[ask[i][1]]-1)-get(dfn[ask[i][1]]-1));
    }
}

【免責聲明】本站內容轉載自互聯網,其相關談吐僅代表作者小我私家概念盡非權勢巨子,不代表本站態度。如您發明內容存在版權成績,請提交相關鏈接至郵箱:,咱們將實時予以處置。