hdu 4348 To the moon

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4348

題目大意:支持區間求和,成段更新和回到歷史版本,訪問歷史版本。

題目思路:我用的解題報告的離線方法,在線方法不會。。(以下摘自解題報告)

在線方法:
1. 帶標記的主席樹(利用路徑指針實現的函數式的線段樹。。
。。可以實現 O(1) 的回檔。。和 O(logN) 的詢問。。
(但是對內存要求較爲苛刻。
2. 主席數組(利用 Fat Node 實現的函數式樹狀數組。。。
樹狀數組的每個結點維護一個記錄時間戳的棧,
詢問的時候用二分查找。總的複雜度 O(nlog^2n)。。。。
對 Backup 操作。。我們使用暴力彈棧。。每個結點至多被彈出一次,總共 O(nlogn) 個結點。。 
離線做法: 
。。堆維護詢問,棧維護操作。。。每次遇到 Backup 操作,則彈出所有至此時刻的詢問。。
最後再彈到 0 時刻即可。。每個操作入棧出棧各一次。。複雜度 O(nlogn)。。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define Max 110000
int max(int a,int b)
{
	return a>b?a:b;
}
int min(int a,int b)
{
	return a<b?a:b;
}
int val[Max];
__int64 rec[Max];
__int64 ans;
struct node
{
    int l,r;
    __int64 sum,add;
    int mid()
    {
        return (l+r)>>1;
    }
}T[4*Max];
struct op
{
    int tp,t,l,r,d,id;
    bool operator<(const op a)const
    {
        return t<a.t;
    }
}a[4*Max];
void up(int rt)
{
    T[rt].sum=T[rt<<1].sum+T[rt<<1|1].sum;
}
void down(int rt)
{
    if(T[rt].l==T[rt].r||T[rt].add==0) return;
    T[rt<<1].sum+=T[rt].add*(T[rt<<1].r-T[rt<<1].l+1);
    T[rt<<1|1].sum+=T[rt].add*(T[rt<<1|1].r-T[rt<<1|1].l+1);
    T[rt<<1].add+=T[rt].add;
    T[rt<<1|1].add+=T[rt].add;
    T[rt].add=0;
}
void build(int l,int r,int rt)
{
    T[rt].l=l;T[rt].r=r;
    T[rt].add=0;
    if(l==r)
    {
        T[rt].sum=val[l];
        return ;
    }
    int mid=T[rt].mid();
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    up(rt);
}
void modify(int l,int r ,int rt,__int64 data)
{
    down(rt);
    if(T[rt].l==l&&T[rt].r==r)
    {
        T[rt].sum+=data*(T[rt].r-T[rt].l+1);
        T[rt].add+=data;
        return;
    }
    int mid=T[rt].mid();
    if(l>mid)
        modify(l,r,rt<<1|1,data);
    else if(r<=mid)
        modify(l,r,rt<<1,data);
    else
    {
        modify(l,mid,rt<<1,data);
        modify(mid+1,r,rt<<1|1,data);
    }
    up(rt);
}
void query(int l,int r,int rt)
{
    down(rt);
    if(T[rt].l==l&&T[rt].r==r)
    {
        ans+=T[rt].sum;
        return;
    }
    int mid=T[rt].mid();
    if(l>mid)
        query(l,r,rt<<1|1);
    else if(r<=mid)
        query(l,r,rt<<1);
    else
    {
        query(l,mid,rt<<1);
        query(mid+1,r,rt<<1|1);
    }
}
char s[10];
int main()
{
    int i,n,m,l,r,d,t;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        stack<op>stk;
        priority_queue<op>q;
        int stamp=0;
        op opt,tmp;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);
        }
        build(1,n,1);
        opt.t=0;
        opt.l=1;opt.r=n;opt.d=0;
        stk.push(opt);
        for(i=0;i<=m;i++)
        {
            if(i==m) s[0]='B';
            else
            scanf("%s",s);
            if(s[0]=='C')
            {
                scanf("%d%d%d",&l,&r,&d);
                modify(l,r,1,d);
                a[i].l=l;a[i].r=r;a[i].d=-d;a[i].id=i;a[i].tp=0;
                stamp++;
                a[i].t=stamp;
                stk.push(a[i]);
            }
            else if(s[0]=='Q')
            {

                scanf("%d%d",&l,&r);
                ans=0; a[i].tp=1;
                query(l,r,1);
                rec[i]=ans;
            }
            else if(s[0]=='H')
            {
                scanf("%d%d%d",&l,&r,&t);
                a[i].l=l;a[i].r=r;a[i].t=t;a[i].id=i; a[i].tp=2;
                q.push(a[i]);
            }
            else
            {
                if(i<m)
                scanf("%d",&t);
                else t=0;
                a[i].tp=3;
                while(!stk.empty())
                {
                    opt=stk.top();
                    stamp=opt.t;
                    while(!q.empty())
                    {
                        tmp=q.top();
                        if(tmp.t<stamp) break;
                        q.pop();
                        ans=0;
                        query(tmp.l,tmp.r,1);
                        rec[tmp.id]=ans;
                    }
                    if(opt.t==t)break;
                    stk.pop();
                    modify(opt.l,opt.r,1,opt.d);
                }
                stamp=t;
            }
        }
        for(i=0;i<m;i++)
        {
            if(a[i].tp==1||a[i].tp==2)
                printf("%I64d\n",rec[i]);
        }
    }
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章