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;
}