SPOJ GSS

以下内容参考了这里
SPOJ的GSS系列是一些与序列和有关的题目,可以拿来做线段树练手题…
为方便提交,我加上了题目连接…话说有人知道怎么在SPOJ搜题吗?窝只能 Google

GSS1:

题目大意:
给定一个序列,求某区间内最大的连续和
题解:
用一棵线段树维护即可,维护 lmax (该区间内包括左端点的最大的连续和), rmax (该区间内包括右端点的最大连续和), mmax (该区间内的最大连续和), sum (该区间元素的和)四个域
代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN=int(5*1e4+5);
int s,t;
int read(){
    int r=0;char c;bool sign=0;
    while(c=getchar(),c=='-'?sign=1:0,!isdigit(c));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return sign?-r:r;
}

struct Sta{
    int lmax,rmax,mmax,sum;
    Sta(int x=0){lmax=rmax=mmax=sum=x;}
    Sta operator + (const Sta& b) const {
        Sta ans;
        ans.sum=sum+b.sum;
        ans.lmax=max(lmax,sum+b.lmax);
        ans.rmax=max(b.rmax,b.sum+rmax);
        ans.mmax=max(max(mmax,b.mmax),rmax+b.lmax);
        return ans;
    }
};struct SGT{
    SGT *ls,*rs;
    int l,r,mid;
    Sta sta;
    SGT(){}
    SGT(int l,int r):ls(NULL),rs(NULL),l(l),r(r){mid=l+r>>1;}
    void Build();
    void Push_Up(){sta=ls->sta+rs->sta;}
    Sta Query(){
        if(s<=l && t>=r) return sta;
        if(s<=mid && t>mid) return ls->Query()+rs->Query();
        return s<=mid?ls->Query():rs->Query();
    }
}*root,mp[MAXN<<2]; int cnt=0;
SGT* New(int l,int r){
    mp[cnt]=SGT(l,r);
    return &mp[cnt++];
}void SGT::Build(){
    if(l==r) {sta=Sta(read());return;}
    (ls=New(l    ,mid))->Build();
    (rs=New(mid+1,r  ))->Build();
    Push_Up();
}

int main(){
    int n=read();
    (root=New(1,n))->Build();
    int m=read();
    while(m--){
        s=read();t=read();
        printf("%d\n",root->Query().mmax);
    }
    return 0;
}
GSS2:

题目大意:
在GSS1的基础上,要求在每个连续和中,重复数字只算一次
题解:
离线大法好,将查询按右端点排序,从左到右依次处理,当前位置为 i ,线段树每个节点代表区间[l,i]内的信息,每增加一个元素k,就更新区间 [pos[a[i]] (上个值为 a[i] 的元素出现的地方) +1,i] ,当 i 为要查询区间的右边界时,只需输出[l,r]的历史最大值,因此,每个结点需要维护当前值与历史最大值.由于需要区间修改, tag 也需要当前 tag 与历史最大 tag
代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN=int(1e5+5),INF=0xc0c0c0c0;
int s,t,c;
int ans[MAXN],a[MAXN],Pos[MAXN<<1];
int read(){
    int r=0;char c;bool sign=0;
    while(c=getchar(),c=='-'?sign=1:0,!isdigit(c));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return sign?-r:r;
}struct Q{
    int l,r,id;
    bool operator < (const Q &b) const {return r<b.r;}
    void Read(int i) {l=read();r=read();id=i;}
}q[MAXN];
struct SGT{
    SGT *ls,*rs;
    int l,r,mid;
    int add,_add,mmax,_mmax;
    SGT(){}
    SGT(int l,int r):ls(0x0),rs(0x0),l(l),r(r){mid=l+r>>1;add=_add=mmax=_mmax=0;}
    void Build();
    void Push_Up() {mmax=max(ls->mmax,rs->mmax); _mmax=max(ls->_mmax,rs->_mmax);}
    void _Add(int c) {_add=max(_add,add+c);_mmax=max(_mmax,mmax+c);}
    void Add(int c) {add+=c;mmax+=c;}
    void Push_Down(){
        if(_add) ls->_Add(_add),rs->_Add(_add),_add=0;
        if( add) ls-> Add( add),rs-> Add( add), add=0;
    }void Up_Data(){
        if(s<=l&&t>=r) {_Add(c);Add(c);return;}
        Push_Down();
        if(s<=mid) ls->Up_Data();
        if(t> mid) rs->Up_Data();
        Push_Up();
    }int Query(){
        if(s<=l&&t>=r) return _mmax;
        Push_Down();
        int ans=INF;
        if(s<=mid) ans=max(ans,ls->Query());
        if(t> mid) ans=max(ans,rs->Query());
        return ans;
    }
}*root,mp[MAXN<<2];int cnt=0;
SGT* New(int l,int r){
    mp[cnt]=SGT(l,r);
    return &mp[cnt++];
}void SGT::Build(){
    if(l==r) return;
    (ls=New(    l,mid))->Build();
    (rs=New(mid+1,  r))->Build();
}

int main(){
    int *pos=Pos+MAXN;
    int n=read();
    (root=New(1,n))->Build();
    for(int i=1;i<=n;i++) a[i]=read();
    int m=read();
    for(int i=0;i<m;i++) q[i].Read(i);
    sort(q,q+m);
    for(int i=1,j=0;i<=n && j<m;i++){
        s=pos[a[i]]+1,t=i=pos[c=a[i]]=i;
        root->Up_Data();
        for(;j<m && i==q[j].r;j++){
            s=q[j].l,t=q[j].r;
            ans[q[j].id]=root->Query();
        }
    }
    for(int i=0;i<m;i++) printf("%d\n",ans[i]);
    return 0;
}
GSS3:

题目大意:
在GSS1的基础上加上单点修改
代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN=int(5*1e4+5);
int s,t,v,c;
int read(){
    int r=0;char c;bool sign=0;
    while(c=getchar(),c=='-'?sign=1:0,!isdigit(c));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return sign?-r:r;
}

struct Sta{
    int lmax,rmax,mmax,sum;
    Sta(int x=0){lmax=rmax=mmax=sum=x;}
    Sta operator + (const Sta& b) const {
        Sta ans;
        ans.sum=sum+b.sum;
        ans.lmax=max(lmax,sum+b.lmax);
        ans.rmax=max(b.rmax,b.sum+rmax);
        ans.mmax=max(max(mmax,b.mmax),rmax+b.lmax);
        return ans;
    }
};struct SGT{
    SGT *ls,*rs;
    int l,r,mid;
    Sta sta;
    SGT(){}
    SGT(int l,int r):ls(NULL),rs(NULL),l(l),r(r){mid=l+r>>1;}
    void Build();
    void Up_Data(){
        if(l==r) {sta=Sta(c);return;}
        v<=mid?ls->Up_Data():rs->Up_Data();
        Push_Up();
    }void Push_Up(){sta=ls->sta+rs->sta;}
    Sta Query(){
        if(s<=l && t>=r) return sta;
        if(s<=mid && t>mid) return ls->Query()+rs->Query();
        return s<=mid?ls->Query():rs->Query();
    }
}*root,mp[MAXN<<2]; int cnt=0;
SGT* New(int l,int r){
    mp[cnt]=SGT(l,r);
    return &mp[cnt++];
}void SGT::Build(){
    if(l==r) {sta=Sta(read());return;}
    (ls=New(l    ,mid))->Build();
    (rs=New(mid+1,r  ))->Build();
    Push_Up();
}

int main(){
    int n=read();
    (root=New(1,n))->Build();
    int m=read();
    while(m--){
        int op=read();
        if(op) s=read(),t=read(),printf("%d\n",root->Query().mmax);
        else v=read(),c=read(),root->Up_Data();
    }
    return 0;
}
GSS4:

题目大意:
给定一个序列,支持对某区间所有元素开根号(下取整)的操作,查询某区间内元素和
题解:
注意到一个数连续开根号后会变为1,我们直接暴力修改就行,修改前判断某区间的和是否等于区间长度,相等的话就不用修改,在修改时,可以使用并查集将已经变为1的连在一起,直接跳过,具体实现可以参考代码
代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN=int(1e5+5);
int n;
LL a[MAXN],tree[MAXN];
int readint(){
    int r=0;char c;
    while(!isdigit(c=getchar()));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return r;
}LL read(){
    LL r=0;char c;
    while(!isdigit(c=getchar()));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return r;
}

int p[MAXN];
void Init() {for(int i=1;i<=n+1;i++) p[i]=i;}
int P(int x) {return x==x?x:p[x]=P(x);}

void Add(int i,LL c) {for(;i<=n;i+=i&(-i)) tree[i]+=c;}
LL Sum(int i) {LL sum=0; for(;i>=1;i-=i&(-i)) sum+=tree[i]; return sum;}
void Change(int l,int r){
    if(Sum(r)-Sum(l-1)==r-l+1) return;
    for(int i=P(l);i<=r;i=P(i+1)){
        if(a[i]^1) {
            Add(i,-a[i]),Add(i,a[i]=LL(sqrt(a[i])));
            if(a[i]==1) p[i]=i+1;
        }
    }
}

int main(){
    int T=0;
    while(scanf("%d",&n)==1){
        printf("Case #%d:\n",++T);
        memset(tree,0,sizeof tree);
        Init();
        for(int i=1;i<=n;i++) Add(i,a[i]=read());
        int m=readint();
        while(m--){
            int op=readint(),l=readint(),r=readint();
            if(l>r) swap(l,r);
            if(op) printf("%lld\n",Sum(r)-Sum(l-1));
            else Change(l,r);
        }
        puts("");
    }
    return 0;
}
GSS5:

题目大意:
在GSS1的基础上,将查询操作改为在区间 [l,r](l[x1,y1],r[x2,y2],x1<x2,y1<y2) 中最大的连续和
题解:
只需对GSS1的修改操作稍加改变,进行分类即可,具体可以参考代码
代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN=int(1e4+5),INF=0xc0c0c0c0;
int num[MAXN];
int read(){
    int r=0;char c;bool sign=0;
    while(c=getchar(),c=='-'?sign=1:0,!isdigit(c));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return sign?-r:r;
}struct Sta{
    int lmax,rmax,mmax,sum;
    Sta(int x=0){lmax=rmax=mmax=sum=x;}
    Sta operator + (const Sta& b) const {
        Sta c;
        c.sum=sum+b.sum;
        c.lmax=max(lmax,sum+b.lmax);
        c.rmax=max(b.rmax,b.sum+rmax);
        c.mmax=max(max(mmax,b.mmax),rmax+b.lmax);
        return c;
    }
};struct SGT{
    SGT *ls,*rs;
    int l,r,mid;
    Sta sta;
    SGT(){}
    SGT(int l,int r):ls(0x0),rs(0x0),l(l),r(r){mid=l+r>>1;}
    void Build();
    void Push_Up() {sta=ls->sta+rs->sta;}
    Sta Query(int s,int t){
        if(s>t) return Sta();
        if(s<=l && t>=r) return sta;
        if(s<=mid && t>mid) return ls->Query(s,t)+rs->Query(s,t);
        return s<=mid?ls->Query(s,t):rs->Query(s,t);
    }
}*root,mp[MAXN<<5];int cnt=0;
SGT* New(int l,int r){
    mp[cnt]=SGT(l,r);
    return &mp[cnt++];
}void SGT::Build(){
    if(l==r) {sta=Sta(num[l]);return;}
    (ls=New(    l,mid))->Build();
    (rs=New(mid+1,  r))->Build();
    Push_Up();
}

int main(){
    int T=read();
    while(T--){
        int n=read();
        for(int i=1;i<=n;i++) num[i]=read();
        (root=New(1,n))->Build();
        int m=read();
        while(m--){
            int a=read(),b=read(),x=read(),y=read(),_max=INF;
            if(b<x) _max=root->Query(a,b).rmax+root->Query(b+1,x-1).sum+root->Query(x,y).lmax;
            else
                _max=max(_max,root->Query(a,x).rmax+root->Query(x,y).lmax-num[x]),
                _max=max(_max,root->Query(a,b).rmax+root->Query(b,y).lmax-num[b]),
                _max=max(_max,root->Query(x,b).mmax);//QAQ 这里之前写反了...
            printf("%d\n",_max);
        }
    }
    return 0;
}
GSS6:

题目大意:
在GSS3的基础上加上插入与删除操作
题解:
用Splay维护序列即可
代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN=int(1e5+5),INF=0xc0c0c0c0;
int n;
int a[MAXN];
int read(){
    int r=0;char c;bool sign=0;
    while(c=getchar(),c=='-'?sign=1:0,!isdigit(c));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return sign?-r:r;
}

#define ls s[0]
#define rs s[1]
struct Node{
    Node *p,*s[2];
    int lmax,rmax,mmax,sum,x,sz;
    Node(){}
    Node(int x);
    int lr() {return p->rs==this;}
    Node* Link(int d,Node* p);
    void Push_Up(){
        sz=ls->sz+1+rs->sz;
        sum=ls->sum+x+rs->sum;
        lmax=max(ls->lmax,ls->sum+x+max(0,rs->lmax));
        rmax=max(rs->rmax,rs->sum+x+max(0,ls->rmax));
        mmax=max(max(0,ls->rmax)+x+max(0,rs->lmax),max(ls->mmax,rs->mmax));
    }
}*null=new Node(INF),*root,node[MAXN<<1];
stack<Node*> mp;
Node* New(int x){
    Node *p=mp.top();mp.pop();
    *p=Node(x);
    return p;
}void Del(Node *p) {mp.push(p);}

Node::Node(int x){
    p=ls=rs=null;
    sz=null?1:0;
    lmax=rmax=mmax=x;
    this->x=sum=x^INF?x:0;
}Node* Node::Link(int d,Node *p) {s[d]=p;return p==null?this:p->p=this;}

void Rtt(Node* o){
    Node *p=o->p,*g=p->p;
    int d=o->lr();
    o->Link(d^1,p->Link(d,o->s[d^1]));
    p->Push_Up();
    g==null?(o->p=null,root=o):g->Link(g->rs==p,o);
}void Splay(Node *p,Node *tar){
    while(p->p!=tar&&p->p->p!=tar)
        p->lr()==p->p->lr()?(Rtt(p->p),Rtt(p)):(Rtt(p),Rtt(p));
    if(p->p!=tar) Rtt(p);
    p->Push_Up();
}void Find(int k,Node *tar){
    Node *p=root;
    for(int d=p->ls->sz;(d+1)^k;d=p->ls->sz)
        k<=d?p=p->ls:(k-=d+1,p=p->rs);
    Splay(p,tar);
}Node* Build(int l,int r){
    if(l==r) return New(a[l]);
    int mid=l+r>>1;
    Node *p=New(a[mid]);
    l<mid?p->Link(0,Build(l,mid-1)):0;
    r>mid?p->Link(1,Build(mid+1,r)):0;
    return p->Push_Up(),p;
}void Init(){
    n=read();
    for(int i=0;i<n<<1;i++) mp.push(&node[i]);
    for(int i=1;i<=n;i++) a[i]=read();
    root=New(0);
    Node *p=New(0);
    root->Link(1,p->Link(0,Build(1,n)));
    p->Push_Up(); root->Push_Up();
}

#define ans root->rs->ls
int main(){
    Init();
    int m=read();
    while(m--){
        char op[3];
        int l;
        scanf("%s",op);
        switch (op[0]){
            case 'I':Find(l=read(),null);Find(l+1,root);
                     root->rs->Link(0,New(read()));root->rs->Push_Up();root->Push_Up();
                     break;
            case 'D':Find(l=read(),null);Find(l+2,root);
                     Del(ans);ans=null;root->rs->Push_Up();root->Push_Up();
                     break;
            case 'R':Find(read()+1,null);root->x=read();root->Push_Up(); break;
            case 'Q':Find(read(),null);Find(read()+2,root);printf("%d\n",ans->mmax); break;
        }
    }
    return 0;
}
GSS7:

题目大意:
将GSS1扔到树上…
题解:
树剖orLink/Cut Tree
不过窝建议没有受虐倾向还是不要写树剖的好,由于树剖查询时链不是连续的,所以合并时很麻烦且易错…
反正窝树剖写了5k,调了三晚上,Link/Cut Tree 3k,写了1h左右…
Link/Cut Tree代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN=int(1e5+5),INF=39980641;
int read(){
    int r=0;char c;bool sign=0;
    while(c=getchar(),c=='-'?sign=1:0,!isdigit(c));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return sign?-r:r;
}

#define ls s[0]
#define rs s[1]
struct Node{
    Node *p,*s[2];
    int lmax,rmax,mmax,sum,x;
    int set,rev,sz;
    Node(){}
    Node(int _);
    int lr() {return p->rs==this;}
    int In() {return p->rs==this||p->ls==this;}
    Node *Link(int d,Node *p);
    void Push_Up(){
        sz=ls->sz+1+rs->sz;
        lmax=max(ls->lmax,ls->sum+x+max(0,rs->lmax));
        rmax=max(rs->rmax,rs->sum+x+max(0,ls->rmax));
        sum=ls->sum+x+rs->sum;
        mmax=max(max(ls->mmax,rs->mmax),max(0,ls->rmax)+x+max(0,rs->lmax));
    }
    void Rev();
    void Set(int c);
    void Push_Down();
}*null=new Node(INF),tree[MAXN];
Node::Node(int _){
    p=ls=rs=null;
    null?(sz=1,lmax=rmax=mmax=sum=x=_):(sz=sum=x=0,lmax=rmax=mmax=-INF);
    set=INF;rev=0;
}Node* Node::Link(int d,Node *p) {s[d]=p;return p==null?this:p->p=this;}
void Node::Rev() {if(this==null) return; rev^=1;swap(ls,rs),swap(lmax,rmax);}
void Node::Set(int c) {if(this==null) return; set=x=c;sum=x*sz;lmax=rmax=mmax=max(sum,x);}
void Node::Push_Down(){
    if(In()) p->Push_Down();
    rev?(ls->Rev(),rs->Rev(),rev=0):0;
    set^INF?(ls->Set(set),rs->Set(set),set=INF):0;
}

#define tu (&tree[u])
#define tv (&tree[v])
void Rtt(Node *o){
    Node *p=o->p,*g=p->p;
    int d=o->lr(),k=p->In();
    o->Link(d^1,p->Link(d,o->s[d^1]));
    p->Push_Up();
    k?g->Link(g->rs==p,o):o->p=g;
}void Splay(Node *p){
    p->Push_Down();
    while(p->In()&&p->p->In())
        p->lr()==p->p->lr()?(Rtt(p->p),Rtt(p)):(Rtt(p),Rtt(p));
    if(p->In()) Rtt(p);
    p->Push_Up();
}void Access(Node *u){
    for(Node *v=null;u!=null;v=u,u=u->p)
        Splay(u),u->rs=v,u->Push_Up();
}void Link(){
    int u=read(),v=read();
    Access(tu);Splay(tu);tu->Rev();
    tu->p=tv;
}

void Init(){
    int n=read();
    for(int u=1;u<=n;u++) tree[u]=Node(read());
    n--;
    while(n--) Link();
}void Query(){
    int u=read(),v=read();
    Access(tu);Splay(tu);tu->Rev();
    Access(tv);Splay(tv);
    printf("%d\n",max(0,tv->mmax));
}void Change(){
    int u=read(),v=read();
    Access(tu);Splay(tu);tu->Rev();
    Access(tv);Splay(tv);
    tv->Set(read());
}

int main(){
    Init();
    int m=read();
    while(m--){
        int op=read();
        if(op==1) Query();
        else Change();
    }
    return 0;
}

树剖代码:

#include <bits/stdc++.h>
using namespace std;

int const MAXN=int(1e5+5),INF=39980641;
int s,t,c,idx=1;
int a[MAXN];
vector<int> g[MAXN];
int pos[MAXN],ipos[MAXN],top[MAXN],p[MAXN],dep[MAXN],siz[MAXN],son[MAXN];
int read(){
    int r=0;char c;bool sign=0;
    while(c=getchar(),c=='-'?sign=1:0,!isdigit(c));
    while(r=r*10+c-'0',isdigit(c=getchar()));
    return sign?-r:r;
}

struct Sta{
    int lmax,rmax,mmax,sum;
    Sta(int x=0) {x^INF?(lmax=rmax=mmax=sum=x):(lmax=rmax=mmax=-INF,sum=x=0);}
    Sta operator + (const Sta& b) const {
        Sta c;
        c.sum=sum+b.sum;
        c.lmax=max(lmax,sum+b.lmax);
        c.rmax=max(b.rmax,b.sum+rmax);//这里错一发...
        c.mmax=max(max(mmax,b.mmax),rmax+b.lmax);
        return c;
    }
};Sta Rev(Sta sta) {swap(sta.lmax,sta.rmax);return sta;}
struct SGT{
    SGT *ls,*rs;
    int l,r,mid,set;
    Sta sta;
    SGT(){}
    SGT(int l,int r):ls(0x0),rs(0x0),l(l),r(r){mid=l+r>>1;set=INF;}
    void Build();
    void Set(int c) {sta.sum=(r-l+1)*c;sta.lmax=sta.rmax=sta.mmax=max(c,sta.sum);set=c;}//更新错误一发...
    void Push_Up() {sta=ls->sta+rs->sta;}
    void Push_Down() {set^INF?(ls->Set(set),rs->Set(set),set=INF):0;}
    void Up_Data(){
        if(s<=l&&t>=r) {Set(c);return;}
        Push_Down();
        if(s<=mid) ls->Up_Data();
        if(t> mid) rs->Up_Data();
        Push_Up();
    }Sta Query(){
        if(s<=l&&t>=r) return sta;
        Push_Down();
        if(s<=mid&&t>mid) return ls->Query()+rs->Query();
        return s<=mid?ls->Query():rs->Query();
    }
}*root,mp[MAXN<<1];int cnt=0;
SGT* New(int l,int r) {mp[cnt]=SGT(l,r);return &mp[cnt++];}
void SGT::Build(){
    if(l==r) {sta=Sta(a[ipos[l]]);return;}
    (ls=New(l,mid))->Build();
    (rs=New(mid+1,r))->Build();
    Push_Up();//忘上传错一发...QAQ
}

void Add(int u,int v) {g[u].push_back(v);g[v].push_back(u);}
void DFS_1(int u){
    son[u]=0;siz[u]=1;
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(v==p[u]) continue;
        p[v]=u;dep[v]=u+1;
        DFS_1(v);
        siz[u]+=siz[v];
        siz[v]>siz[son[u]]?son[u]=v:0;
    }
}void DFS_2(int u,int t){
    ipos[pos[u]=idx++]=u;top[u]=t;
    if(son[u]) DFS_2(son[u],t);
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(v==son[u]||v==p[u]) continue;
        DFS_2(v,v);
    }
}void Init(){
    int n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<n;i++) Add(read(),read());
    dep[1]=1;
    DFS_1(1);DFS_2(1,1);
    (root=New(1,n))->Build();
}

int Query(){
    int u=read(),v=read(),d=0;
    Sta sta[2];
    sta[0]=sta[1]=Sta(INF);
    for(int fu=top[u],fv=top[v];fu^fv;fu=top[u=p[fu]]){
        if(dep[fu]<dep[fv]) swap(u,v),swap(fu,fv),d^=1;;
        s=pos[fu],t=pos[u];
        sta[d]=d?root->Query()+sta[d]:sta[d]+Rev(root->Query());
    }
    if(dep[u]>dep[v]) swap(u,v); else d^=1;
    s=pos[u],t=pos[v];
    sta[d]=d?root->Query()+sta[d]:sta[d]+Rev(root->Query());
    return (sta[0]+sta[1]).mmax;
}void Up_Data(){
    int u=read(),v=read();c=read();
    for(int fu=top[u],fv=top[v];fu^fv;fu=top[u=p[fu]]){
        if(dep[fu]<dep[fv]) swap(u,v),swap(fu,fv);
        s=pos[fu],t=pos[u];
        root->Up_Data();
    }
    if(dep[u]>dep[v]) swap(u,v);
    s=pos[u],t=pos[v];
    root->Up_Data();
}

int main(){
    Init();
    int m=read();
    while(m--){
        int op=read();
        if(op==1) printf("%d\n",max(0,Query()));
        else Up_Data();
    }
    return 0;
}
GSS8:

题目大意:
在GSS6的基础上把元素的范围扩大了…
题解:
窝还没写,估计会卡常?先挖个坑…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值