码迷,mamicode.com
首页 > 其他好文 > 详细

COJ WZJ的数据结构(负三十三)

时间:2015-08-05 14:32:19      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

 

WZJ的数据结构(负三十三)
难度级别:E; 运行时间限制:7000ms; 运行空间限制:262144KB; 代码长度限制:2000000B
试题描述

请你设计一个数据结构,完成以下功能:

给定一个大小为N的整数组A,要求你回答执行N次操作。操作分两种:

操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数。

操作2:每次操作给你l,r,v三个参数,将Al至Ar所有数的值设为v。

输入
第一行为一个正整数N。
第二行为N个整数Ai。
接下来N行每行4个正整数t,l,r,v。若t=2表示操作1,t=1表示操作2。
输出
对每个操作1输出结果。
输入示例
6
1 2 2 1 2 3
2 1 4 2
2 1 4 1
1 2 4 1
2 1 4 1
1 3 5 2
2 2 5 2
输出示例
4
2
4
4
其他说明
1<=N<=200000
1<=Ai,v<=10^9

XYZ大爷论文题“一个简单的序列问题”。

一上午的青春全部奉献给这道题了(3棵线段树调得我要报警)。

先将区间修改转化成带删除的区间插入,用一棵线段树来做。

再用线段树分治将问题转化成静态问题,用一棵线段树和2个nlogn的邻接表。

最后排序后转化成区间加与区间查询的问题,用一棵线段树来做。

说起来真是简单呢!

技术分享
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==-) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-0;
    return x*f;
}
const int maxn=400010;
struct Query {
    int tp,l,r,x,begin,end,id;
    bool operator < (const Query& ths) const {return begin<ths.begin;}
}Q[maxn],Q2[maxn*3];
struct Solver {
    int id,l,r,x;
    bool operator < (const Solver& ths) const {return x<ths.x||(x==ths.x&&id<ths.id);}
}A[maxn*3];
int n,ans[maxn],m;
int setv[maxn*3],is[maxn*3];
void pushdown(int o) {
    int lc=o<<1,rc=lc|1;
    if(setv[o]) {
        setv[lc]=setv[rc]=setv[o];
        is[lc]=is[rc]=1;
        setv[o]=0;
    }
}
int lastv,L,R;
void find(int o,int l,int r,int v) {
    if(!is[o]) return;
    if(setv[o]) {
        if(setv[o]==lastv) R=r;
        else {
            if(lastv!=-1) Q2[++m]=(Query){1,L,R,Q[lastv].x,lastv,v-1,Q[lastv].id};
            lastv=setv[o];L=l;R=r;
        }
        setv[o]=0;
    }
    else if(l<r) {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        find(lc,l,mid,v);find(rc,mid+1,r,v);
    }
    is[o]=0;
}
void update(int o,int l,int r,int ql,int qr,int v) {
    if(ql<=l&&r<=qr) find(o,l,r,v),setv[o]=v;
    else {
        pushdown(o);
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        if(ql<=mid) update(lc,l,mid,ql,qr,v);
        if(qr>mid) update(rc,mid+1,r,ql,qr,v);
    }
    is[o]=1;
}
int first1[maxn*3],next1[maxn*20],id1[maxn*20],ToT1;
int first2[maxn*3],next2[maxn*20],id2[maxn*20],ToT2,N;
void query(int o,int l,int r,int pos,int v) {
    N=max(N,o);
    id1[++ToT1]=v;next1[ToT1]=first1[o];first1[o]=ToT1;
    if(l==r) return;
    int mid=l+r>>1,lc=o<<1,rc=lc|1;
    if(pos<=mid) query(lc,l,mid,pos,v);
    else query(rc,mid+1,r,pos,v);
}
void modify(int o,int l,int r,int ql,int qr,int v) {
    N=max(N,o);
    if(ql<=l&&r<=qr) {
        id2[++ToT2]=v;next2[ToT2]=first2[o];first2[o]=ToT2;
    }
    else {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        if(ql<=mid) modify(lc,l,mid,ql,qr,v);
        if(qr>mid) modify(rc,mid+1,r,ql,qr,v);
    }
}
int addv[maxn*3],sumv[maxn*3];
void pushdown2(int o,int l,int r) {
    int mid=l+r>>1,lc=o<<1,rc=lc|1;
    if(addv[o]) {
        addv[lc]+=addv[o];addv[rc]+=addv[o];
        sumv[lc]+=addv[o]*(mid-l+1);sumv[rc]+=addv[o]*(r-mid);
        addv[o]=0;
    }
}
void update2(int o,int l,int r,int ql,int qr,int v) {
    int mid=l+r>>1,lc=o<<1,rc=lc|1;
    if(ql<=l&&r<=qr) addv[o]+=v;
    else {
        pushdown2(o,l,r);
        if(ql<=mid) update2(lc,l,mid,ql,qr,v);
        if(qr>mid) update2(rc,mid+1,r,ql,qr,v);
    }
    if(l<r) sumv[o]=sumv[lc]+sumv[rc];
    else sumv[o]=0;
    if(addv[o]) sumv[o]+=addv[o]*(r-l+1);
}
int query2(int o,int l,int r,int ql,int qr) {
    if(ql<=l&&r<=qr) return sumv[o];
    pushdown2(o,l,r);
    int mid=l+r>>1,lc=o<<1,rc=lc|1,ans=0;
    if(ql<=mid) ans+=query2(lc,l,mid,ql,qr);
    if(qr>mid) ans+=query2(rc,mid+1,r,ql,qr);
    return ans;
}
int tmp[maxn];
int main() {
    n=read();
    rep(i,1,n) Q[Q[i].id=i].tp=1,Q[i].l=i,Q[i].r=i,Q[i].x=read();
    rep(i,n+1,2*n) Q[Q[i].id=i].tp=read(),Q[i].l=read(),Q[i].r=read(),Q[i].x=read();
    n<<=1;
    Q[n+1].tp=1;Q[n+1].l=1;Q[n+1].r=n>>1;
    rep(i,1,n+1) {
        if(Q[i].tp==1) {
            lastv=-1;
            update(1,1,n>>1,Q[i].l,Q[i].r,i);
            if(lastv!=-1) Q2[++m]=(Query){1,L,R,Q[lastv].x,lastv,i-1,Q[lastv].id};
        }
        else Q2[++m]=Q[i],Q2[m].begin=Q2[m].end=i;
    }
    rep(i,1,m) {
        if(Q2[i].tp==1) modify(1,1,n,Q2[i].begin,Q2[i].end,i);
        else query(1,1,n,Q2[i].begin,i);
    }
    rep(i,1,N) if(first1[i]&&first2[i]) {
        int cnt=0;
        for(int j=first1[i];j;j=next1[j]) A[++cnt]=(Solver){Q2[id1[j]].id,Q2[id1[j]].l,Q2[id1[j]].r,Q2[id1[j]].x};
        for(int j=first2[i];j;j=next2[j]) A[++cnt]=(Solver){0,Q2[id2[j]].l,Q2[id2[j]].r,Q2[id2[j]].x};
        sort(A+1,A+cnt+1);
        rep(j,1,cnt) {
            if(!A[j].id) update2(1,1,n>>1,A[j].l,A[j].r,1);
            else ans[A[j].id]+=query2(1,1,n>>1,A[j].l,A[j].r);
        }
        rep(j,1,cnt) if(!A[j].id) update2(1,1,n>>1,A[j].l,A[j].r,-1);
    } 
    rep(i,1,n) if(Q[i].tp==2) printf("%d\n",ans[i]);
    return 0;
}
View Code

 

COJ WZJ的数据结构(负三十三)

标签:

原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/4704450.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!