spoj 4487. Can you answer these queries VI splay 常数优化

4487. Can you answer these queries VI

Problem code: GSS6

Given a sequence A of N (N <= 100000) integers, you have to apply Q (Q <= 100000) operations:

Insert, delete, replace an element, find the maximum contiguous(non empty) sum in a given interval.

Input

The first line of the input contains an integer N.
The following line contains N integers, representing the starting
sequence A1..AN, (|Ai| <= 10000).

The third line contains an integer Q. The next Q lines contains the operations in following form:

I x y: insert element y at position x (between x - 1 and x).
D x  : delete the element at position x.
R x y: replace element at position x with y.
Q x y: print max{Ai + Ai+1 + .. + Aj | x <= i <= j <= y}.

All given positions are valid, and given values are between -10000 and +10000.

The sequence will never be empty.

Output

For each "Q" operation, print an integer(one per line) as described above.

Example

Input:53 -4 3 -1 610I 6 2Q 3 5R 5 -4Q 3 5D 2Q 1 5I 2 -10Q 1 6R 2 -1Q 1 6

Output:83635

  第二次写splay居然遇上了考splay的常数优化。弄了很久。首先是读入优化,貌似SPOJ上面数据有‘\r‘所以要特殊判断。然后inline所有函数,最后把splay移到一个struct里面会加速很多。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#define MAXN 110000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define MAXT MAXN*2
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define lch splay[now].ch[0]
#define rch splay[now].ch[1]
typedef long long qword;
inline int nextInt()
{
        char ch;
        int x=0;
        bool flag=false;
        do
                ch=(char)getchar(),flag=(ch==‘-‘)?true:flag;
        while(ch<‘0‘||ch>‘9‘);
        do x=x*10+ch-‘0‘;
        while (ch=(char)getchar(),ch<=‘9‘ && ch>=‘0‘);
        return x*(flag?-1:1);
}

int n,m;
int root=0,topt=0;;
struct sss
{
        int lx,rx,mx,val,sum,siz,pnt;
        int ch[2];
}splay[MAXT];
inline void up(int now)
{
        splay[now].lx=splay[now].rx=splay[now].mx=-INF;
        if (lch)splay[now].lx=max(splay[now].lx,splay[lch].lx);
        splay[now].lx=max(splay[now].lx,max(splay[lch].sum+splay[now].val,splay[lch].sum+splay[now].val+splay[rch].lx));

        if (rch)splay[now].rx=max(splay[now].rx,splay[rch].rx);
        splay[now].rx=max(splay[now].rx,max(splay[rch].sum+splay[now].val,splay[rch].sum+splay[now].val+splay[lch].rx));

        splay[now].mx=splay[now].val;
        if (lch)splay[now].mx=max(splay[now].mx,splay[lch].mx);
        if (rch)splay[now].mx=max(splay[now].mx,splay[rch].mx);
        splay[now].mx=max(splay[now].mx,splay[lch].rx+splay[rch].lx+splay[now].val);
        splay[now].mx=max(splay[now].mx,splay[rch].lx+splay[now].val);
        splay[now].mx=max(splay[now].mx,splay[lch].rx+splay[now].val);

        splay[now].siz=splay[lch].siz+splay[rch].siz+1;
        splay[now].sum=splay[lch].sum+splay[rch].sum+splay[now].val;
}

inline void Rotate(int now)
{
        int p=splay[now].pnt,anc=splay[p].pnt;
        int dir=splay[p].ch[0]==now;
        if (anc)
                splay[anc].ch[splay[anc].ch[1]==p]=now;
        splay[now].pnt=anc;

        splay[splay[now].ch[dir]].pnt=p;
        splay[p].ch[1-dir]=splay[now].ch[dir];

        splay[p].pnt=now;
        splay[now].ch[dir]=p;
        up(p);
        up(now);
}
/*
inline int Get_kth(int now,int rk)
{
        if (rk==siz[splay[now].ch[0]]+1)
                return now;
        if (rk<siz[splay[now].ch[0]]+1)
                return Get_kth(splay[now].ch[0],rk);
        else
                return Get_kth(splay[now].ch[1],rk-siz[splay[now].ch[0]]-1);
}*/
inline int Get_kth(int rk)
{
        int now=root;
        while (rk!=splay[splay[now].ch[0]].siz+1)
        {
                if (rk>splay[splay[now].ch[0]].siz+1)
                {
                        rk-=splay[splay[now].ch[0]].siz+1;
                        now=splay[now].ch[1];
                }else
                {
                        now=splay[now].ch[0];
                }
        }
        return now;
}

inline void Splay(int now,int tp=0)
{
        if (now==tp)return ;
        while (splay[now].pnt!=tp)
        {
                int p=splay[now].pnt,anc=splay[p].pnt;
                if (anc==tp)
                        Rotate(now);
                else if( (splay[anc].ch[0]==p) == (splay[p].ch[0]==now))
                {
                        Rotate(p);
                        Rotate(now);
                }else
                {
                        Rotate(now);
                        Rotate(now);
                }
        }
        if (tp==0)root=now;
}
inline void Insert(int pos,int v)
{
        int now=++topt;
        splay[now].ch[0]=splay[now].ch[1]=0;
        splay[now].pnt=0;
        splay[now].val=v;
        splay[now].siz=1;
        splay[now].lx=splay[now].rx=splay[now].mx=splay[now].sum=v;
        if (!pos)
        {
                Splay(Get_kth(1));
                splay[now].ch[1]=root;
                splay[root].pnt=now;
                root=now;
                up(now);
                return ;
        }
        Splay(Get_kth(pos));
        splay[now].pnt=root;
        splay[now].ch[1]=splay[root].ch[1];
        splay[splay[root].ch[1]].pnt=now;
        splay[root].ch[1]=now;
        up(now);
        up(root);
        return ;
}
inline void Delete(int pos)
{
        Splay(Get_kth(pos));
        if (pos!=splay[root].siz)
        {
                Splay(Get_kth(pos+1),root);/**/
                splay[splay[root].ch[1]].ch[0]=splay[root].ch[0];
                splay[splay[root].ch[0]].pnt=splay[root].ch[1];;
                splay[splay[root].ch[1]].pnt=splay[root].pnt;
                root=splay[root].ch[1];
        }else
        {
                root=splay[root].ch[0];
                splay[root].pnt=0;
        }
        up(root);
}
inline int Qry_mxs(int l,int r)
{
        if (l==1 && r==splay[root].siz)
        {
                return splay[root].mx;
        }else if (l==1)
        {
                Splay(Get_kth(r+1));
                return splay[splay[root].ch[0]].mx;
        }else if (r==splay[root].siz)
        {
                Splay(Get_kth(l-1));
                return splay[splay[root].ch[1]].mx;
        }else
        {
                Splay(Get_kth(l-1));
                Splay(Get_kth(r+1),root);
                return splay[splay[splay[root].ch[1]].ch[0]].mx;
        }
}
inline void Chg_val(int pos,int v)
{
        Splay(Get_kth(pos));
        splay[root].val=v;
        up(root);
}
void Scan(int now)
{
        if (!now)return ;
        if (splay[now].siz!=splay[lch].siz+splay[rch].siz+1)throw 2;
        if (splay[now].ch[0])
        {
                if (splay[splay[now].ch[0]].pnt!=now)throw 1;
                Scan(splay[now].ch[0]);
        }
        printf("%d ",splay[now].val);
        if (splay[now].ch[1])
        {
                if (splay[splay[now].ch[1]].pnt!=now)throw 1;
                Scan(splay[now].ch[1]);
        }
}
void Build_tree(int &now,int *num,int l,int r)
{
        now=++topt;
        int mid=(l+r)>>1;
        splay[now].siz=1;
        splay[now].sum=splay[now].val=splay[now].mx=splay[now].lx=splay[now].rx=num[mid];
        if (l<=mid-1)Build_tree(lch,num,l,mid-1);
        if (mid+1<=r)Build_tree(rch,num,mid+1,r);
        splay[lch].pnt=now;
        splay[rch].pnt=now;
        up(now);
}
int num[MAXN];
int main()
{
        freopen("input.txt","r",stdin);
        //freopen("output.txt","w",stdout);
        int i,j,k;
        int x,y,z;
        scanf("%d",&n);
        for (i=0;i<n;i++)
        {
                x=nextInt();
                num[i]=x;
        }
        Build_tree(root,num,0,n-1);
        scanf("%d\n",&m);
        char opt;
        for (i=0;i<m;i++)
        {
                opt=getchar();
                //scanf("%c",&opt);
                if (opt==‘I‘)
                {
                    //    scanf("%d%d",&x,&y);
                        x=nextInt();y=nextInt();
                        x--;
                        Insert(x,y);
                }else if (opt==‘Q‘)
                {
                    //    scanf("%d%d",&x,&y);
                        x=nextInt();y=nextInt();
                        printf("%d\n",Qry_mxs(x,y));
                }else if (opt==‘R‘)
                {
                    //    scanf("%d%d",&x,&y);
                        x=nextInt();y=nextInt();
                        Chg_val(x,y);
                }else if (opt==‘D‘)
                {
                    //    scanf("%d",&x);
                        x=nextInt();
                        Delete(x);
                }
                getchar();
        }
        return 0;
}
				
时间: 2024-08-02 15:12:54

spoj 4487. Can you answer these queries VI splay 常数优化的相关文章

SPOJ 4487. Can you answer these queries VI splay

题目链接:点击打开链接 题意比较明显,不赘述. 删除时可以把i-1转到根,把i+1转到根下 则i点就在 根右子树 的左子树,且只有i这一个 点 #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; #define N 300500 #define inf 10000000 #define L(x) tree[x].ch[

SPOJ GSS6 4487. Can you answer these queries VI (SPLAY)

题目大意: 四个操作: I X Y 在x位置插入y D x 删除x位置的数 R x y 用y替换x位置上的数字 Q x y 求出[x,y]上的最大子序列的和. 思路分析: 对于动态维护序列肯定是splay了. 现在就考虑以下几个问题. 之前我们知道线段树处理连续的子序列的和是用区间合并的.那splay上怎么做. 考虑边界,如儿子为 0 或者是冗余节点怎么办? 初始化的时候将值赋成什么. 仔细考虑这些就能减少代码量. 注意replace的时候,要去找到然后直接修改,如果先旋转的话就会造成超时. #

SPOJ GSS6 Can you answer these queries VI ——Splay

[题目分析] 增加了插入和删除. 直接用Splay维护就好辣! 写了一个晚上,(码力不精),最后发现更新写挂了 [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include

SPOJ GSS6 Can you answer these queries VI

Can you answer these queries VI Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: GSS664-bit integer IO format: %lld      Java class name: Main Given a sequence A of N (N <= 100000) integers, you have to appl

SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树

题目链接:点击打开链接 维护区间左起连续的最大和,右起连续的和.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lson

SPOJ GSS3 Can you answer these queries III (线段树)

题目大意: 求区间最大子区间的和. 思路分析: 记录左最大,右最大,区间最大. 注意Q_L  和 Q_R  就好. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e #define maxn 55555 using na

SPOJ GSS4 Can you answer these queries IV (线段树)

题目大意: 给出N个数 0     操作   把 l -----  r之间的数全部开平方 1     操作  输出 l -----r  之间的和 思路分析: 判断区间里的数字是否全相同.如果相同, 将cov 置为该数 查询的时候和更新的时候,如果碰到cov != -1 的  就直接返回就可以了 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #incl

spoj gss2 : Can you answer these queries II 离线&amp;&amp;线段树

1557. Can you answer these queries II Problem code: GSS2 Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse to write two program of same kind at all. So he always failes in co

SPOJ GSS5 Can you answer these queries V (线段树)

原来有一两个人说我不帅的时候,我不以为意,逗我玩而已,后来几乎所有 人都说我不帅,我才真正意识到事态的严重,这社会骗子真是越来越多了... 好吧我承认,这个笑话不好笑,其实我想说的是,做人一定要坚持自己的原则, 哪怕有一天所有人都和你背道而驰,都不要放弃自己当初的梦想,如果有一天, 我们淹没在人海之中,庸碌一生,那是因为我们不够努力,不够勇敢的去面对生活. 每天积累一点点,嗯,满足简单的快乐. ---------------------------------------------------