Problem tree line summary

Segment tree

Task 1

Static maintenance operation sequence: \ (. 1 \ n-Leq, m \ ^ Leq 10. 5, -15 007 \ Leq a_i \ Leq 15007 \) ,

  • lr: maximum continuous interrogation zone and sub-segment, i.e. asking $ \ max \ limits_ {l \ leq i \ leq j \ leq r} \ sum_ {k = i} ^ j a_k $

Section may be provided four consecutive numerals and sub-segments:

  • \ (sum \) maintenance intervals and
  • \ (lmax \) maintain close range at the left end and maximum continuous sub-segment
  • \ (rmax \) maintain close range right end of the sub-segments and maximum continuous
  • \ (ret \) interval and continuous sub-segments.

Respectively, can be maintained as follows:

  • \(sum_x = sum_{lson} +sum_{rson}\)
  • \(lmax_x = max(lmax_{lson},sum_{lson}+lmax_{rson})\)
  • \(rmax_x = max(rmax_{rson},sum_{rson}+rmax_{lson})\)
  • \ (Ret_x = max (ret_ lson {}, {ret_ rson}, {rmax_ lson} + {lmax_ rson}) \)

The same information time of the merger.

# include<bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+10;
struct Segment_Tree{
    int sum,lmax,rmax,ret;
}tr[N<<2];
int a[N],n;
# define ls (x<<1)
# define rs ((x<<1)+1)
# define lson (x<<1),l,mid
# define rson ((x<<1)+1),mid+1,r
# define mid ((l+r)>>1)
void build(int x,int l,int r)
{
    if (l==r) {
        tr[x].sum=tr[x].lmax=tr[x].rmax=tr[x].ret=a[l];
        return;
    }
    build(lson); build(rson);
    tr[x].sum=tr[ls].sum+tr[rs].sum;
    tr[x].lmax=max(tr[ls].lmax,tr[ls].sum+tr[rs].lmax);
    tr[x].rmax=max(tr[rs].rmax,tr[rs].sum+tr[ls].rmax);
    tr[x].ret=max(max(tr[ls].ret,tr[rs].ret),tr[ls].rmax+tr[rs].lmax);
}
Segment_Tree query(int x,int l,int r,int opl,int opr)
{
    if (opl<=l&&r<=opr) return tr[x];
    if (opr<=mid) return query(lson,opl,opr);
    if (opl>mid) return query(rson,opl,opr);
    Segment_Tree lo=query(lson,opl,mid), ro=query(rson,mid+1,opr) ,ans;
    ans.sum=lo.sum+ro.sum;
    ans.lmax=max(lo.lmax,lo.sum+ro.lmax);
    ans.rmax=max(ro.rmax,ro.sum+lo.rmax);
    ans.ret=max(max(lo.ret,ro.ret),lo.rmax+ro.lmax);
    return ans;
}
signed main()
{
    scanf("%lld",&n);
    for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,1,n);
    int T; scanf("%lld",&T);
    while (T--) {
        int l,r; scanf("%lld%lld",&l,&r);
        printf("%lld\n",query(1,1,n,l,r).ret);
    }
    return 0;
}

Task 2

Maintenance operations on two sequences: \ (. 1 \ n-Leq, m \ Leq 10 5,0 ^ \ Leq a_i \ Leq 18 is 10 ^ {} \)

  • 0 xy expressed \ (i \ in [x, y] \) to perform all the elements \ (= a_i \ sqrt {a_i} \) (lower rounded)
  • 1 xy presents to ask \ (\ sum_ {i = x } ^ y a_i \) values.

Clearly a number of several root is opened and then rounding will eventually become 0/1, and a maximum of 10 times the number of open root becomes 0/1, and no modification operation, so we only need to define a segment times square root can, since each interval start and up to 10 times the square root, the time complexity is \ (O (10 \ times m \ log \ n) \)

I was really drunk, md input in \ (x> y \) are out! ! !

# include <cstdio>
# include <iostream>
# include <cstring>
# include <cmath>
# define max(a,b) ((a)<(b)?(b):(a))
# define min(a,b) ((a)<(b)?(a):(b))
# define int long long
using namespace std;
const int N=1e5+10;
int Lim,n,m,a[N];
struct Segment_Tree{
    int sum,cnt; 
}tr[N<<2];
# define lson ls,l,mid
# define rson rs,mid+1,r
# define mid ((l+r)>>1)
# define ls (x<<1)
# define rs (x<<1|1)
void clear()
{
    memset(tr,0,sizeof(tr));
    memset(a,0,sizeof(a));
    Lim=0;
}
void build(int x,int l,int r)
{
    if (l==r) { tr[x].sum=a[l]; tr[x].cnt=0; return;}
    build(lson); build(rson);
    tr[x].sum=tr[ls].sum+tr[rs].sum;
}
void update(int x,int l,int r,int opl,int opr)
{
    if (tr[x].cnt>=Lim) return;
    if (opl<=l&&r<=opr) tr[x].cnt++;
    if (l==r) { tr[x].sum=sqrt(tr[x].sum); return;}
    if (opl<=mid) update(lson,opl,opr);
    if (opr>mid) update(rson,opl,opr);
    tr[x].sum=tr[ls].sum+tr[rs].sum;
}
int query(int x,int l,int r,int opl,int opr)
{
    if (opl<=l&&r<=opr) return tr[x].sum;
    int ret=0;
    if (opl<=mid) ret+=query(lson,opl,opr);
    if (opr>mid) ret+=query(rson,opl,opr);
    return ret;
}
signed main()
{
    int T=0;
    while (~scanf("%lld",&n)) {
        printf("Case #%lld:\n",++T);
        int Max=0; for (int i=1;i<=n;i++) scanf("%lld",&a[i]),Max=max(Max,a[i]);
        while (Max!=0&&Max!=1) Lim++,Max=sqrt(Max);
        build(1,1,n); scanf("%lld",&m);
        for (int i=1;i<=m;i++) {
            int op,l,r; scanf("%lld%lld%lld",&op,&l,&r);
            if (l>r) swap(l,r);
            if (!op) update(1,1,n,l,r);
            else printf("%lld\n",query(1,1,n,l,r));
        } clear();
        puts("");
    }
    return 0;
}

Task 3

Maintaining a data structure that supports a number of insert, delete a number, find the median of all numbers. $ 1≤n≤10 ^ 4, 1 \ leq T \ leq 100,0 \ leq a_i \ leq 10 ^ 9 $

All discrete number, and then build range segment tree.

Insert a number, delete a number in the range directly to the leaf node tree line in the update.

Query with a tree line to go, son than the father left, right, son bigger than his father, to find the corresponding node through the current remaining rankings k.

Overall complexity $ O (Tn log n) $

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e4+10;
int n,tmp[N],T; queue<int>dq;
struct Segment_Tree{
    int cnt;
}tr[N<<2];
struct Qes{
    int op,x;
}q[N];
# define lson ls,l,mid
# define rson rs,mid+1,r
# define mid (l+r>>1)
# define ls (x<<1)
# define rs (x<<1|1)
void clear()
{
    memset(tr,0,sizeof(tr)); memset(q,0,sizeof(q));
    memset(tmp,0,sizeof(tmp)); 
    while (dq.size()) dq.pop();
}
void insert(int x,int l,int r,int pos)
{
    if (l==r) { tr[x].cnt++; return;}
    if (pos<=mid) insert(lson,pos);
    else insert(rson,pos);
    tr[x].cnt=tr[ls].cnt+tr[rs].cnt;
}
void erase(int x,int l,int r,int pos)
{
    if (l==r) { tr[x].cnt--; return;}
    if (pos<=mid) erase(lson,pos);
    else erase(rson,pos);
    tr[x].cnt=tr[ls].cnt+tr[rs].cnt;
}
int query(int x,int l,int r,int k)
{
    if (l==r) return l;
    if (k<=tr[ls].cnt) return query(lson,k);
    else return query(rson,k-tr[ls].cnt);
}
signed main()
{
    int num=0;
    while (~scanf("%d",&n)) {
        
        for (int i=1;i<=n;i++) {
            char s[10]; scanf("%s",s);
            if (s[0]=='i') scanf("%lld",&q[i].x),q[i].op=0,tmp[++tmp[0]]=q[i].x;
            else if (s[0]=='o') q[i].op=1;
            else q[i].op=2;
        }
        sort(tmp+1,tmp+1+tmp[0]);
        T=unique(tmp+1,tmp+1+tmp[0])-tmp-1;
        printf("Case #%lld:\n",++num);
        for (int i=1;i<=n;i++) {
            if (q[i].op==0) {
                int x=lower_bound(tmp+1,tmp+1+tmp[0],q[i].x)-tmp;
                dq.push(x); insert(1,1,T,x);
            } else if (q[i].op==1) {
                erase(1,1,T,dq.front());
                dq.pop();
            } else if (q[i].op==2) {
                int k=dq.size(); k=k/2+1;
                printf("%lld\n",tmp[query(1,1,T,k)]);
            }
        }
        clear();
    }
    return 0;
}

Task 4

For a given permutation \ (a_i \ in [1, n] \) , do the following: \ (. 1 \ n-Leq, m \ Leq. 5 ^ 10 \)

  • 0 lr: the \ (i \ in [l, r] \) number \ (a_i \) in ascending order;
  • 1 lr: the \ (i \ in [l, r] \) number \ (a_i \) in descending order;

Finally ask, the first (q \) \ number on the position is.

First half answers, each answer for \ (Mid \) the sequence of less than or equal to its \ (0 \) , which is set to greater than \ (1 \) .

So we just need to count how many of them the interval \ (0 \) , the number \ (1 \) to complete the sort.

Segment tree only need to complete the query interval \ (01 \) number, interval assignment \ (01 \) can be.

We need to find a position such that \ (q \) number on position 1, and this position needs to be minimized.

Complexity $ O (m log_2 ^ 2 n) $

# pragma GCC optimize(3)
# include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct Qes{
    int op,l,r;
}q[N];
int n,m,P,a[N];
struct Segment_Tree{
    int cnt0,cnt1,l,r,tag;
    Segment_Tree() { cnt0=cnt1=l=r=tag=0;}
}tr[N<<2];
# define lson ls,l,mid
# define rson rs,mid+1,r
# define ls (x<<1)
# define rs (x<<1|1)
# define mid (l+r>>1)
void up(int x) {
    tr[x].cnt0=tr[ls].cnt0+tr[rs].cnt0;
    tr[x].cnt1=tr[ls].cnt1+tr[rs].cnt1;
}
void build(int x,int l,int r,int val) {
    tr[x].l=l; tr[x].r=r; tr[x].tag=-1;
    if (l==r) { tr[x].cnt0=(a[l]<=val); tr[x].cnt1=(a[l]>val); return;}
    build(lson,val); build(rson,val);
    up(x);
}
void down(int x) {
    if (tr[x].tag==-1) return;
    if (tr[x].tag==0) {
        tr[ls].cnt0=tr[ls].r-tr[ls].l+1; tr[ls].cnt1=0; tr[ls].tag=0;
        tr[rs].cnt0=tr[rs].r-tr[rs].l+1; tr[rs].cnt1=0; tr[rs].tag=0;
    } else {
        tr[ls].cnt1=tr[ls].r-tr[ls].l+1; tr[ls].cnt0=0; tr[ls].tag=1;
        tr[rs].cnt1=tr[rs].r-tr[rs].l+1; tr[rs].cnt0=0; tr[rs].tag=1;
    }
    tr[x].tag=-1;
}
void update(int x,int l,int r,int opl,int opr,int opx) {
    if (opl<=l&&r<=opr) {
        if (opx==0) tr[x].tag=0,tr[x].cnt1=0,tr[x].cnt0=tr[x].r-tr[x].l+1;
        if (opx==1) tr[x].tag=1,tr[x].cnt0=0,tr[x].cnt1=tr[x].r-tr[x].l+1;
        return;
    }
    if (l==r) return;
    down(x);
    if (opl<=mid) update(lson,opl,opr,opx);
    if (opr>mid) update(rson,opl,opr,opx);
    up(x);
}
Segment_Tree query(int x,int l,int r,int opl,int opr) {
    if (opl<=l&&r<=opr) return tr[x];
    down(x); Segment_Tree lo,ro,ans;
    if (opl<=mid) lo=query(lson,opl,opr);
    if (opr>mid) ro=query(rson,opl,opr);
    ans.cnt0=lo.cnt0+ro.cnt0;
    ans.cnt1=lo.cnt1+ro.cnt1;
    return ans;
}
# undef lson
# undef rson
# undef ls
# undef rs
# undef mid
inline int read()
{
    int X=0,w=0; char c=0;
    while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
    while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
    return w?-X:X;
}
bool check(int Mid) {
    build(1,1,n,Mid); 
    for (int i=1;i<=m;i++) if (q[i].op==0) {
        Segment_Tree ans=query(1,1,n,q[i].l,q[i].r);
        update(1,1,n,q[i].l,q[i].l+ans.cnt0-1,0);
        update(1,1,n,q[i].l+ans.cnt0,q[i].r,1);
    } else {
        Segment_Tree ans=query(1,1,n,q[i].l,q[i].r);
        update(1,1,n,q[i].l,q[i].l+ans.cnt1-1,1);
        update(1,1,n,q[i].l+ans.cnt1,q[i].r,0);
    }
    Segment_Tree ans=query(1,1,n,P,P);
    return ans.cnt0;
}
int main() {
    n=read();m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=m;i++) q[i].op=read(),q[i].l=read(),q[i].r=read();
    P=read(); int l=1,r=n,ans=-1;
    while (l<=r) { 
        int mid=(l+r)>>1;
        if (check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}

Task 5

$ N $ points to a tree, a point \ (1 \) is the root node of the tree and the right bit \ (a_i \) . There are $ M $ operations:

  • 1 xw: the right to a node x point increase in w.
  • 2 xw: the subtree rooted at some node x of weights of all points are point increase w.
  • 3 x: ask the right path to a point x to the root node points and all.

To 100% data $ 1 \ leq N, M \ leq 10 ^ 5, -10 ^ 6 \ leq w, a_i \ leq 10 ^ 6 $

Chain split tree directly on the line. Liver is $ O (n \ log_2 ^ 2 n) $
I have not heard anything dfs tree line

# include <cstdio>
# include <iostream>
# include <cstring>
# define int long long
# define MAXN 200005
using namespace std;
typedef long long ll;
int n,m,r,val[MAXN],b[MAXN];
struct Tree{
    ll c[MAXN];
    int lowbit(int x){ return x&(-x);}
    void update(int x,int y){
        while (x<=n){
            c[x]+=y;
            x+=lowbit(x);
        }
    }
    ll query(int x){
        ll ret=0;
        while (x>0){
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
}c1,c2;
struct Edge{
    int pre,to;
}a[2*MAXN];
int head[MAXN],tot=0;
void adde(int u,int v)
{
    a[++tot].pre=head[u];
    a[tot].to=v;
    head[u]=tot;
}
ll getsum(int l,int r)
{
    return (ll) c1.query(r)*r-c2.query(r)-(l-1)*c1.query(l-1)+c2.query(l-1);
}
int f[MAXN],dep[MAXN],son[MAXN],size[MAXN];
void dfs1(int u,int fa,int depth)
{
    f[u]=fa;dep[u]=depth;size[u]=1;
    for (int i=head[u];i;i=a[i].pre)
    {
        int v=a[i].to; if (v==fa) continue;
        dfs1(v,u,depth+1);
        size[u]+=size[v];
        if (size[son[u]]<size[v]) son[u]=v;
    }
}
int w[MAXN],cntw=0,top[MAXN],old[MAXN];
void dfs2(int u,int tp)
{
    w[u]=++cntw;top[u]=tp;
    old[cntw]=u;
    if (son[u]!=0) dfs2(son[u],tp);
    for (int i=head[u];i;i=a[i].pre)
    {
        int v=a[i].to; if (v==f[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}
void change(int u,int v,int d)
{
    int f1=top[u],f2=top[v];
    while (f1!=f2){
        if (dep[f1]<dep[f2]) swap(f1,f2),swap(u,v);
        c1.update(w[f1],d);
        c1.update(w[u]+1,-d);
        c2.update(w[f1],d*(w[f1]-1));
        c2.update(w[u]+1,-d*w[u]);
        u=f[f1];
        f1=top[u];
    }
    if (dep[u]<dep[v]) swap(u,v);
    c1.update(w[v],d);
    c1.update(w[u]+1,-d);
    c2.update(w[v],d*(w[v]-1));
    c2.update(w[u]+1,-d*w[u]);
}
ll lca(int u,int v)
{
    int f1=top[u],f2=top[v];
    ll ret=0ll;
    while (f1!=f2){
        if (dep[f1]<dep[f2]) swap(f1,f2),swap(u,v);
        ret=ret+getsum(w[f1],w[u]);
        u=f[f1];
        f1=top[u];
    }
    if (dep[u]<dep[v]) swap(u,v);
    ret=ret+getsum(w[v],w[u]);
    return ret;
}
signed main()
{
    scanf("%lld%lld",&n,&m); r=1; 
    for (int i=1;i<=n;i++) scanf("%lld",&val[i]);
    int u,v;
    for (int i=1;i<=n-1;i++) {
        scanf("%lld%lld",&u,&v);
        adde(u,v); adde(v,u);
    }
    dfs1(r,0,0);
    dfs2(r,0);
    for (int i=1;i<=n;i++) b[i]=val[old[i]];
    for (int i=1;i<=n;i++) c1.update(i,b[i]-b[i-1]),c2.update(i,(b[i]-b[i-1])*(i-1));
    int ch,x,y,z;
    for (int i=1;i<=m;i++) {
        scanf("%lld%lld",&ch,&x);
        if (ch==1) scanf("%lld",&z),change(x,x,z);
        else if (ch==2) {
            scanf("%lld",&z);
            int l=w[x],r=w[x]+size[x]-1;
            c1.update(l,z); c1.update(r+1,-z);
            c2.update(l,z*(l-1)); c2.update(r+1,-z*r);
        } else {
             printf("%lld\n",lca(x,1));
        }
    }
    return 0;
}

Task 6

Maintenance operations on two sequences: \ (. 1 \ n-Leq, m \ Leq 10 5,0 ^ \ Leq a_i \ Leq 18 is 10 ^ {} \)

  • add x represents the \ (X \) is added to the set which
  • 1 xy presents to ask \ (\ sum_ {i = x } ^ y a_i \) values.

The words of the title written so able to live ah!

#pragma GCC optimize(3)
# include <bits/stdc++.h>
using namespace std;
vector<int>a;
int n;
char s[10];
int main(){
    scanf("%d",&n); int x;
    while (n--) {
        scanf("%s",s);
        if (s[0]=='a') cin>>x,a.insert(lower_bound(a.begin(),a.end(),x),x);
        else if (s[0]=='d') cin>>x,a.erase(lower_bound(a.begin(),a.end(),x));
        else { long long ret=0; for (int i=2;i<a.size();i+=5) ret=ret+a[i]; printf("%lld\n",ret);}
    }
    return 0;
}

Task 7

Gives a number of requirements, \ (L_i, r_i, Q_I \) represents \ (a [l_i] \ & a [l_i + 1] \ & ... \ & a [r_i] = q_i \)

If there is an array of \ (a \) the output line \ (YES \) and then outputs a legitimate array. Otherwise, the output line \ (NO \) .

To 100% of the data \ (\ leq n \ leq 10 ^ 5, q_i \ leq 2 ^ {30} \)

Each binary can be pulled out of, respectively, the processing for each bit

If an interval \ (l, r \) range $ 1 and $ value, then that this range must be all \ (1 \)

So we are directly assigned to this interval \ (1 \) can be.

Then ask to do it again for each check, to determine the legality of that look is \ (0 \) on the position \ (l, r \) is not all \ (1 \) , it is 1 once, then back and forth conflicts output \ (NO \) .

Above can be used to maintain the differential prefix and maintenance. Complexity is \ (O (n \ log_2 \ n) \)

# include<bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+10;
int n,Q,c[31][N],ans[31][N];
struct rec{ int l,r,d; }q[N];
void update(int l,int r,int d)
{
    for (int i=30;i>=0;i--)
        if (d&(1ll<<i)) c[i][l]++,c[i][r+1]--;
}
void init()
{
    for (int i=0;i<=30;i++) for (int j=1;j<=n;j++) c[i][j]=c[i][j-1]+c[i][j];
    for (int i=0;i<=30;i++) for (int j=1;j<=n;j++) c[i][j]=(c[i][j]>0);
    memcpy(ans,c,sizeof(c));
    for (int i=0;i<=30;i++) for (int j=1;j<=n;j++) c[i][j]=c[i][j-1]+c[i][j];
}
bool check(int l,int r,int d)
{
    for (int i=30;i>=0;i--)
     if ((!(d&(1ll<<i)))&&(c[i][r]-c[i][l-1]==r-l+1)) return false;
    return true;
}
signed main()
{
    scanf("%lld%lld",&n,&Q);
    for (int i=1;i<=Q;i++) {
        scanf("%lld%lld%lld",&q[i].l,&q[i].r,&q[i].d);
        update(q[i].l,q[i].r,q[i].d);
    }
    init();
    for (int i=1;i<=Q;i++)
        if (!check(q[i].l,q[i].r,q[i].d)) { puts("NO"); return 0; }
    puts("YES");
    for (int i=1;i<=n;i++) {
        int ret=0;
        for (int j=0;j<=30;j++) if (ans[j][i]) ret+=(1<<j);
        printf("%lld ",ret);
    }
    return 0;
}

Task 8

Gives \ (n \) digital array \ (a_i \) to divide it into a continuous \ (k \) segments, each segment of the value of this period is the number of different numbers of miles, and the maximum value is to ask how much.

To 100% of the data \ (n \ leq 35000, k \ leq min (n, 50) \)

\ (f [i] [j ] \) representing the forward \ (I \) th array is divided into \ (J \) section and a maximum value.

$ f[i][j] = \max\limits_{j-1 \leq k \leq i-1}{ f[k][j-1] + w(k+1,j) }$

Wherein \ (w (l, r) \) representing the interval \ ([l, r] \ ) Unique number of values.

Optimization Consider seeking $ \ max \ limits_ {j-1 \ leq k \ leq i-1} {f [k] [j-1] + w (k + 1, j)} $

First, the outer loop enumeration \ (J \) , the inner loop enumeration \ (I \) , then the first interval assigned \ (f [k] [j -1] \)

Each number recorded position before the first occurrence of \ (pos [i] \) for each number \ (I \) be \ ([pos [i] + 1, i-1] \) generating \ (1 \) contributions, direct-line segment tree can add interval.

Available transfer segment tree maintenance complexity \ (O (nk \ log_2 n ) \)

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+10,M=55;
int a[N],w[N],pos[N],pre[N],n,k;
int f[N][M];
struct Segment_Tree{
    int tag,mx;
}tr[N<<2];
# define lson ls,l,mid
# define rson rs,mid+1,r
# define mid (l+r>>1)
# define ls (x<<1)
# define rs (x<<1|1)
void build(int x,int l,int r)
{
    tr[x].tag=0; tr[x].mx=0;
    if (l==r) { tr[x].mx=w[l]; return;}
    build(lson); build(rson);
    tr[x].mx=max(tr[ls].mx,tr[rs].mx);
}
void down(int x)
{
    if (!tr[x].tag) return;
    tr[ls].mx+=tr[x].tag; tr[rs].mx+=tr[x].tag;
    tr[ls].tag+=tr[x].tag; tr[rs].tag+=tr[x].tag;
    tr[x].tag=0;
}
void update(int x,int l,int r,int opl,int opr,int d)
{
    if (opl<=l&&r<=opr) { tr[x].tag+=d; tr[x].mx+=d; return;}
    down(x);
    if (l==r) return;
    if (opl<=mid) update(lson,opl,opr,d);
    if (opr>mid) update(rson,opl,opr,d);
    tr[x].mx=max(tr[ls].mx,tr[rs].mx);
}
int query(int x,int l,int r,int opl,int opr)
{
    if (opl<=l&&r<=opr) return tr[x].mx;
    down(x);
    int ret=0;
    if (opl<=mid) ret=max(ret,query(lson,opl,opr));
    if (opr>mid) ret=max(ret,query(rson,opl,opr));
    return ret;
}
signed main()
{
    scanf("%lld%lld",&n,&k);
    for (int i=1;i<=n;i++) {
        scanf("%lld",&a[i]);
        pos[i]=pre[a[i]];
        pre[a[i]]=i;
    }
    for (int j=1;j<=k;j++) {
        for (int i=1;i<=n;i++) w[i]=f[i-1][j-1];
        build(1,1,n);
        for (int i=1;i<=n;i++) {
            update(1,1,n,pos[i]+1,i,1);
            f[i][j]=query(1,1,n,1,i);
        }
    }
    printf("%lld\n",f[n][k]);
    return 0;
}

Task 9

One containing \ (n-\) tree nodes, maintain the following two operations:

  • 1 uv said it would point the right node u + v, his son right point node -v, the son of his son's point right + v ... until a leaf node.
  • 2 u u node represents the point of the right to obtain

100% of the data \ (1 \ leq n, m \ leq 2 \ times 10 ^ 5 \)

Dfs tree node sequence is continuous. We maintain an array \ (c [u] \) represents the node (u \) \ increments.

This \ (c [u] \) processing array is relatively simple, direct sequence dfs tree corresponding to the interval plus.

But if the operation in the depth odd and even number of different nodes, the contribution would be contrary to the answer.

If the depth is odd record an increased amount, to reduce the amount of recording is an even depth.

The final answer is plus or minus initial contribution.

Complexity is \ (O (n \ log_2 \ n) \)

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=2e5+10;
struct rec{ int pre,to; }a[N<<1];
int L[N],R[N],c[N],v[N],head[N],dep[N];
int n,tot,cnt,m;
void adde(int u,int v)
{
    a[++tot].pre=head[u];
    a[tot].to=v;
    head[u]=tot;
}
void dfs(int u,int fa)
{
    L[u]=++cnt; dep[u]=dep[fa]+1;
    for (int i=head[u];i;i=a[i].pre) {
        int v=a[i].to; if (v==fa) continue;
        dfs(v,u);
    }
    R[u]=cnt;
}
# define lowbit(x) (x&(-x))
void update(int x,int y){for (;x<=n;x+=lowbit(x)) c[x]+=y;}
int query(int x){int ret=0; for (;x;x-=lowbit(x)) ret+=c[x]; return ret;}
void modify(int l,int r,int d){update(l,d); update(r+1,-d);}
signed main()
{
    scanf("%lld%lld",&n,&m);
    for (int i=1;i<=n;i++) scanf("%lld",&v[i]);
    for (int i=1;i<n;i++) {
        int u,v; scanf("%lld%lld",&u,&v);
        adde(u,v); adde(v,u);
    }
    dfs(1,0);
    for (int i=1;i<=m;i++) {
        int op,x; scanf("%lld%lld",&op,&x);
        if (op==1) {
            int d; scanf("%lld",&d);
            if (dep[x]&1) modify(L[x],R[x],d);
            else modify(L[x],R[x],-d);
        } else {
            if (dep[x]&1) printf("%lld\n",v[x]+query(L[x]));
            else printf("%lld\n",v[x]-query(L[x]));
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/ljc20020730/p/11291465.html