【JZOJ 5295】【清华集训2017模拟】Create

来源:互联网 发布:unity3d 工业仿真 编辑:程序博客网 时间:2024/05/19 19:43

Description

这里写图片描述

Solution

题目有一个比较显然的性质:因为我们不停的把连续的一段变成一个数的话,那么全局不同的数会越来越少;换句话说,就是如果我们在区间修改时,对于一个数都相同的区间我们才能修改,这样均摊下来复杂度并不是很高,

所以,现在的问题就变成了:如何快速求一段数相同的区间内对答案的贡献,

设这个区间的值为c,那么只有v小于等于c的三元组才有可能有贡献,
而贡献为多少,则是这个区间被这些可能的三元组覆盖的总面积(这么写大家看得懂吧。。。),

这个是标准的主席树嘛,

这样的复杂度为O(nlog(n)2),可能过不了,
我们发现,在主席树上遍历的过程和在线段树上的很像,考虑两个同时进行,这样既可。

Code

#include <cstdio>#include <cstdlib>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define min(q,w) ((q)>(w)?(w):(q))#define max(q,w) ((q)<(w)?(w):(q))#define CNT(L,R,E) (finds(1,n,root[fef[E]],L,R))#define NW(e1,e) if(!(e)||(e1)==(e))b[(e)=++b0]=b[e1];using namespace std;typedef long long LL;const int N=100500;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int m,n;LL ans;int a[N];struct qqww{    int v,la,s;}b1[N*4];int root[N],b0;struct qwqw{    int l,r,v;    int la;}b[N*70];int sc[N][3],p[N],pn;int fef[N];bool PX(int q,int w){return sc[q][2]<sc[w][2];}void build(int l,int r,int e1,int e,int l1,int r1){    if(l1<=l&&r<=r1)    {        b[e].la++;        b[e].v+=(r-l+1);        return;    }    b[e].v+=(r1-l1+1);    int t=(l+r)>>1;    if(r1<=t)    {        NW(b[e1].l,b[e].l);        build(l,t,b[e1].l,b[e].l,l1,r1);    }    else if(t<l1)    {        NW(b[e1].r,b[e].r);        build(t+1,r,b[e1].r,b[e].r,l1,r1);    }    else     {        NW(b[e1].l,b[e].l);NW(b[e1].r,b[e].r);        build(l,t,b[e1].l,b[e].l,l1,t),build(t+1,r,b[e1].r,b[e].r,t+1,r1);    }}int finds(int l,int r,int e,int l1,int r1){    if(!e)return 0;    if(l1==l&&r1==r)return b[e].v;    int t=(l+r)>>1;    int ans=(r1-l1+1)*b[e].la;    if(r1<=t)ans+=finds(l,t,b[e].l,l1,r1);    else if(t<l1)ans+=finds(t+1,r,b[e].r,l1,r1);    else ans+=finds(l,t,b[e].l,l1,t)+finds(t+1,r,b[e].r,t+1,r1);    return ans;}void merge(int l,int r,int e){    if(b1[e*2].v==b1[e*2+1].v&&b1[e*2].v!=-1)    {        b1[e].v=b1[e*2].v;        int t=(l+r)>>1;        if(b1[e*2].s==-1)b1[e*2].s=CNT(l,t,b1[e].v);        if(b1[e*2+1].s==-1)b1[e*2+1].s=CNT(t+1,r,b1[e].v);        b1[e].s=b1[e*2].s+b1[e*2+1].s;    }else b1[e].v=-1,b1[e].s=-1;}void build(int l,int r,int e){    if(l==r)    {        b1[e].v=a[l];        ans+=(b1[e].s=CNT(l,r,a[l]));        return;    }    int t=(l+r)>>1;    build(l,t,e*2);    build(t+1,r,e*2+1);    merge(l,r,e);}inline void doit(int l,int r,int e){    if(!b1[e].la)return;    b1[e].v=b1[e].la;    b1[e].s=-1;    if(l!=r)b1[e*2].la=b1[e].la,b1[e*2+1].la=b1[e].la;    b1[e].la=0;}void change(int l,int r,int e,int l1,int r1,int l2){    int t=(l+r)>>1;    if(l!=r)doit(l,t,e*2),doit(t+1,r,e*2+1);    if(l1<=l&&r<=r1)    {        if(b1[e].v!=-1)        {            if(b1[e].s==-1)b1[e].s=CNT(l,r,b1[e].v);            ans-=b1[e].s;            b1[e].la=l2;            doit(l,r,e);            b1[e].s=CNT(l,r,b1[e].v);            ans+=b1[e].s;            return;        }    }    if(r1<=t)change(l,t,e*2,l1,r1,l2);    else if(t<l1)change(t+1,r,e*2+1,l1,r1,l2);    else change(l,t,e*2,l1,t,l2),change(t+1,r,e*2+1,t+1,r1,l2);    merge(l,r,e);}int main(){    freopen("create.in","r",stdin);    freopen("create.out","w",stdout);    int q,w,e,_;    read(n),read(m),read(_);    fo(i,1,n)read(a[i]);    fo(i,1,m)    {        p[i]=i;        fo(j,0,2)read(sc[i][j]);    }    sort(p+1,p+1+m,PX);    sc[0][2]=-2333;    w=0;    fo(i,1,m)    {        w+=(sc[q][2]!=sc[p[i]][2]);        q=p[i];        NW(root[w-1],root[w])        build(1,n,root[w-1],root[w],sc[q][0],sc[q][1]);        p[w]=sc[q][2];    }    pn=w;    fo(i,1,pn)fef[p[i]]=i;    fo(i,1,n+1)if(!fef[i])fef[i]=fef[i-1];    ans=0;    build(1,n,1);    printf("%d\n",ans);    fo(i,1,_)    {        read(q),read(w),read(e);        q^=ans;w^=ans;e^=ans;        change(1,n,1,q,w,e);        printf("%lld\n",ans);    }    fclose(stdout);    fclose(stdin);    return 0;}
阅读全文
0 0