【JZOJ5295】【清华集训2017模拟】Create
2017-08-23 07:52
429 查看
Description
Data Constraint
Solution
这道题很经典。我们发现一次操作最多使序列多出1段新的连续序列。所以我们考虑维护这个序列。我们将询问按x大小排序后建一棵主席树,那么对于一个修改(l,r,v),我们可以算出修改后(l,r)对答案的贡献。现在问题是怎样取消修改前的贡献。我们用线段树维护每一段连续的颜色的起点和终点。每一次修改暴力跳一下每个颜色段,查询他们原来的贡献。即可撤销修改前的贡献。时间复杂度O(Qlogm)。
Code
#include<iostream> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> #include<set> #define ll long long using namespace std; const ll maxn=1e5+5; struct code{ ll l,r,num,bz; bool friend operator < (code x,code y){ return x.l<y.l; } }f[maxn*60]; struct code1{ ll l,r,x; }b[maxn]; ll r[maxn],l[maxn],a[maxn],d[maxn],g[maxn*4],g1[maxn*4],ans1[maxn]; ll n,m,q,i,t,j,k,x,y,z,num,ans,xx,yy,p,qq; bool cmp(code1 x,code1 y){ return x.x<y.x; } void insert(ll l,ll r,ll &v,ll x,ll y){ ll mid=(l+r)/2; f[++num]=f[v];v=num; if (l>=x && r<=y){ f[v].bz++;f[v].num+=r-l+1;return; } if (mid>=x) insert(l,mid,f[v].l,x,y); if (mid<y) insert(mid+1,r,f[v].r,x,y); f[v].num=(r-l+1)*f[v].bz+f[f[v].l].num+f[f[v].r].num; } void find(ll l,ll r,ll v,ll x,ll y){ ll mid=(l+r)/2; if (!f[v].num)return; if (l>=x && r<=y){ k+=f[v].num; return; }else k+=(min(r,y)-max(x,l)+1)*f[v].bz; if (mid>=x) find(l,mid,f[v].l,x,y); if (mid<y) find(mid+1,r,f[v].r,x,y); } void build(ll l2,ll rr,ll v){ ll mid=(l2+rr)/2; if (l2==rr){ g[v]=l[l2];g1[v]=r[l2]; return; } build(l2,mid,v*2);build(mid+1,rr,v*2+1); } void find1(ll l,ll r,ll v,ll x){ ll mid=(l+r)/2; if (l==r){ p=g[v];q=g1[v];return; } if (g[v]) g[v*2]=g[v*2+1]=g[v],g[v]=0; if (g1[v]) g1[v*2]=g1[v*2+1]=g1[v],g1[v]=0; if (x>mid) find1(mid+1,r,v*2+1,x); else find1(l,mid,v*2,x); } void change(ll l,ll r,ll v,ll x,ll y){ if (x>y) return; ll mid=(l+r)/2; if (l>=x && r<=y){ g[v]=x;g1[v]=y;return; } if (g[v]) g[v*2]=g[v*2+1]=g[v],g[v]=0; if (g1[v]) g1[v*2]=g1[v*2+1]=g1[v],g1[v]=0; if (mid<y) change(mid+1,r,v*2+1,x,y); if (mid>=x) change(l,mid,v*2,x,y); } ll pan(ll x){ ll l=0,r=m,mid; while (l<r){ mid=(l+r+1)/2; if (b[mid].x<=x) l=mid; else r=mid-1; } return l; } int main(){ freopen("create.in","r",stdin);freopen("create.out","w",stdout); scanf("%lld%lld%lld",&n,&m,&qq); for (i=1;i<=n;i++){ scanf("%lld",&a[i]); if (a[i]==a[i-1]) l[i]=l[i-1]; else l[i]=i; } for (i=n;i>=1;i--) if (a[i]==a[i+1]) r[i]=r[i+1]; else r[i]=i; build(1,n,1); for (i=1;i<=m;i++) scanf("%lld%lld%lld",&b[i].l,&b[i].r,&b[i].x); sort(b+1,b+m+1,cmp); for (i=1;i<=m;i++){ d[i]=d[i-1]; insert(1,n,d[i],b[i].l,b[i].r); } i=1; while (i<=n){ t=pan(a[i]);k=0; find(1,n,d[t],i,r[i]); i=r[i]+1,ans+=k; } printf("%lld\n",ans); for (i=1;i<=qq;i++){ scanf("%lld%lld%lld",&x,&y,&z);x^=ans;y^=ans;z^=ans; k=0;t=pan(z); find(1,n,d[t],x,y);ans+=k; xx=x;find1(1,n,1,xx); change(1,n,1,p,xx-1); while (xx<=y){ find1(1,n,1,xx); k=0;t=pan(a[p]); find(1,n,d[t],xx,min(q,y));ans-=k; xx=min(q,y)+1; } change(1,n,1,y+1,q);if (y+1<=q)a[y+1]=a[p]; change(1,n,1,x,y);a[x]=z; printf("%lld\n",ans); } }
相关文章推荐
- 【JZOJ 5295】【清华集训2017模拟】Create
- 【JZOJ5295】【清华集训模拟】Create(主席树)
- [jzoj]5483. 【清华集训2017模拟11.26】简单路径
- JZOJ 5489. 【清华集训2017模拟11.28】海明距离
- [JZOJ5498]【清华集训2017模拟12.10】大佬的难题
- JZOJ5498. 【清华集训2017模拟12.10】大佬的难题
- JZOJ 5490. 【清华集训2017模拟11.28】图染色
- JZOJ5489. 【清华集训2017模拟11.28】海明距离
- JZOJ 5496. 【清华集训2017模拟12.09】Tree
- jzoj5498 【清华集训2017模拟12.10】大佬的难题 巧妙容斥
- 【JZOJ 5284】【清华集训2017模拟】超级翻转
- 【JZOJ5316】【清华集训2017模拟8.19】merge
- 【JZOJ 5296】【清华集训2017模拟】Sequence
- JZOJ 5484. 【清华集训2017模拟11.26】快乐树
- [JZOJ5485]【清华集训2017模拟11.26】字符串
- [JZOJ5500]【清华集训2017模拟12.10】营养餐
- [JZOJ5495]【清华集训2017模拟12.09】MiniumCut
- JZOJ 5489. 【清华集训2017模拟11.28】海明距离
- JZOJ5483. 【清华集训2017模拟11.26】简单路径
- 【清华集训2017模拟】Create