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

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
contests.

When having a contest, Yang Zhe looks at the score of every
problems first. For the problems of the same score, Yang Zhe will
do only one of them. If he‘s lucky enough, he can get all the scores
wanted.

Amber is going to hold a contest in SPOJ. She has made a list of
N candidate problems, which fit Yang Zhe very well. So Yang
Zhe can solve any problem he want. Amber lined up the problems,
began to select. She will select a subsequence of the list as the
final problems. Being A girl of great compassion, she‘d like to
select such a subsequence (can be empty) that Yang Zhe will get the
maximal score over all the possible subsequences.

Amber found the subsequence easily after a few minutes. To make
things harder, Amber decided that, Yang Zhe can take this contest
only if Yang Zhe can answer her Q questions. The question is:
if the final problems are limited to be a subsequence
of list[X..Y] (1 <= X <= Y <= N),
what‘s the maximal possible score Yang Zhe can get?

As we know, Yang Zhe is a bit idiot (so why did he solve the
problem with a negative score?), he got Wrong Answer again... Tell
him the correct answer!

Input

  • Line 1: integer N (1 <= N <= 100000);
  • Line 2: N integers denoting the score of each problem,
    each of them is a integer in range [-100000, 100000];
  • Line 3: integer Q (1 <= Q <= 100000);
  • Line 3+i (1 <= i <= Q): two
    integers X and
    Y denoting the ith question.

Output

  • Line i: a single integer, the answer to the ith
    question.

Example

Input:
9
4 -2 -2 3 -1 -4 2 2 -6
3
1 2
1 5
4 9

Output:
4
5
3

  见过变态的线段树,没见过这么变态的。。。。。。  在我看来,这个线段树lazy标记的传递奇葩之处在于用到了lazy标记传递的一个隐藏的规律:即某个标记被改变意味着它上方不存在其他标记,因此一个标记下放时,其下方标记作用的时间域和此标记是没有交集的。  我做这道题参考的题解:http://blog.csdn.net/acm_cxlove/article/details/7854526  (注意一下:那个题解的标程没开long long)  两个lazy标记:lazy:标记代表的那一段时间区间增加的量    lazy2:对应时间区间增加量的最值  维护两个值:mx:这个区间当前最大值    his:这个区间历史最大值  其他参见连接题解。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXQ 110000
#define MAXR 200200
#define VAL1 100100
#define MAXN 101000
#define MAXT 410000
#define lch (now<<1)
#define rch (now<<1^1)
#define INFL 0x3f3f3f3f3f3f3f3fLL
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
typedef long long qword;
int n,m;
struct node
{
        int l,r;
        qword mx;
        qword his;
        qword lazy;//delta
        qword lazy2;//delta_max
}tree[MAXT];
void down(int now)
{
        if (tree[now].l==tree[now].r)
        {
                tree[now].lazy=0;
                tree[now].lazy2=0;
                return ;
        }
        tree[lch].lazy2=max(tree[lch].lazy2,tree[lch].lazy+tree[now].lazy2);
        tree[rch].lazy2=max(tree[rch].lazy2,tree[rch].lazy+tree[now].lazy2);
        tree[lch].his=max(tree[lch].his,tree[lch].mx+tree[now].lazy2);
        tree[rch].his=max(tree[rch].his,tree[rch].mx+tree[now].lazy2);
        tree[lch].mx+=tree[now].lazy;
        tree[rch].mx+=tree[now].lazy;
        tree[lch].lazy+=tree[now].lazy;
        tree[rch].lazy+=tree[now].lazy;
        tree[now].lazy=0;
        tree[now].lazy2=0;
}
void up(int now)
{
        if (tree[now].l==tree[now].r)return ;
        tree[now].mx=max(tree[lch].mx,tree[rch].mx);
        tree[now].his=max(tree[lch].his,tree[rch].his);
}
void build_tree(int now,int l,int r)
{
        tree[now].l=l;
        tree[now].r=r;
        tree[now].his=0;
        tree[now].lazy=0;
        tree[now].lazy2=0;
        tree[now].mx=0;
        if (l==r)
        {
                return ;
        }
        int mid=(l+r)/2;
        build_tree(lch,l,mid);
        build_tree(rch,mid+1,r);
}
void add_val(int now,int l,int r,qword z)
{
        if (l==tree[now].l&&r==tree[now].r)
        {
                tree[now].lazy+=z;
                tree[now].lazy2=max(tree[now].lazy2,tree[now].lazy);
                tree[now].mx+=z;
                tree[now].his=max(tree[now].mx,tree[now].his);
                return ;
        }
        down(now);
        int mid=(tree[now].l+tree[now].r)/2;
        if (r<=mid)
        {
                add_val(lch,l,r,z);
                up(now);
                return ;
        }
        if (mid<l)
        {
                add_val(rch,l,r,z);
                up(now);
                return ;
        }
        add_val(lch,l,mid,z);
        add_val(rch,mid+1,r,z);
        up(now);
}
qword get_max(int now,int l,int r)
{
        if (l==tree[now].l&&r==tree[now].r)
        {
                return tree[now].his;
        }
        int mid=(tree[now].l+tree[now].r)/2;
        down(now);
        if (r<=mid)
        {
                return get_max(lch,l,r);
        }
        if (mid<l)
        {
                return get_max(rch,l,r);
        }
        qword t;
        t= max(get_max(lch,l,mid),get_max(rch,mid+1,r));
        up(now);
        return t;
}
int num[MAXN];
int rec[MAXR];
int prev[MAXN];
struct qur_t
{
        int x,y,id;
        qword ans;
}qur[MAXQ];
bool cmp_y(const qur_t &q1,const qur_t &q2)
{
        return  q1.y<q2.y;
}
bool cmp_id(const qur_t &q1,const qur_t &q2)
{
        return q1.id<q2.id;
}
int main()
{
        freopen("input.txt","r",stdin);
        int i,j,k,x,y,z;
        scanf("%d",&n);
        memset(rec,-1,sizeof(rec));
        for (i=0;i<n;i++)
        {
                scanf("%d",&num[i]);
                prev[i]=rec[num[i]+VAL1];
                rec[num[i]+VAL1]=i;
        }
        scanf("%d",&m);
        for (i=0;i<m;i++)
        {
                scanf("%d%d",&qur[i].x,&qur[i].y);
                qur[i].x--;
                qur[i].y--;
                qur[i].id=i;
        }
        sort(qur,&qur[m],cmp_y);
        int now=-1;
        build_tree(1,0,n-1);
        for (i=0;i<m;i++)
        {
                while (now<qur[i].y)
                {
                        now++;
        //                cout<<"Add:"<<prev[now]+1<<"~"<<now<<":"<<num[now]<<endl;
                        add_val(1,prev[now]+1,now,num[now]);
                }
        //        cout<<"Query:"<<qur[i].x<<"~"<<qur[i].y<<endl;
                qur[i].ans=get_max(1,qur[i].x,qur[i].y);
        }
        sort(qur,&qur[m],cmp_id);
        //    cout<<"a"<<endl;
        for(i=0;i<m;i++)
        {
                printf(LL "\n",qur[i].ans);
        }
}
 

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

时间: 2024-10-12 12:40:04

spoj gss2 : Can you answer these queries II 离线&&线段树的相关文章

SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)

GSS2 - Can you answer these queries II #tree 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 contests. When

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

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

bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树

2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 145  Solved: 76[Submit][Status][Discuss] Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和(可选空子段). 这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次. 比如:1,2,3,2,2,2出现了3次,但只算一次,

SPOJ GSS2 Can you answer these queries II

Time Limit: 1000MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description 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

【SPOJ - GSS2】Can you answer these queries II(线段树)

区间连续不重复子段最大值,要维护历史的最大值和当前的最大值,打两个lazy,离线 #include<cstdio> #include<cstring> #include<algorithm> #define maxn 150000 #define rep(i,l,r) for(int i=l;i<=r;i++) #define LL long long using namespace std; typedef struct { LL nmax,hmax,nlazy

spoj 1716 Can you answer these queries III(线段树)

和I相比有了单点更新,所以不能只记录一个前缀和,而是要在线段树上多维护一个sum,表示这个结点的区间和,然后其他的就和I一样了. #include <iostream>#include <cstring>#include <cstdio>using namespace std; const int N = 50001;int a[N]; struct Node { int l, r, sum; int maxl, maxr, maxn;} node[N <<

Spoj 2713 Can you answer these queries IV 水线段树

题目链接:点击打开链接 题意: 给定n长的序列 下面2个操作 0 x y 给[x,y]区间每个数都 sqrt 1 x y 问[x, y] 区间和 #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #include <vector> #includ

SPOJ 1557. Can you answer these queries II 线段树

Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/problems/GSS2/ Description Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse

V - Can you answer these queries? HDU - 4027 线段树

V - Can you answer these queries? HDU - 4027 这个题目开始没什么思路,因为不知道要怎么去区间更新这个开根号. 然后稍微看了一下题解,因为每一个数开根号最多开十几次就变成1了,所以就直接单点更新,但是这个可以剪枝. 如果碰到区间长度和区间大小相同就可以不用更新了. 我也是无语了,想到刚刚的做法之后很好写了, 不过要注意以下x,y 大小可能x>y, 这个bug如果不是之前看题解的时候瞄到了,我可能找不出来了. 因为我写对拍我肯定会保证x<y 的,还是就是