Cry_For_theMoon  

前言:

这个题非常搞人心态。

垃圾题。

垃圾题。

垃圾题。

分析:

这么复杂的操作感觉没有 polylog 做法,考虑根号做法(然后被jsz神仙用 \(n\log^2 n\) 的线段树分治A了orz)。

好像没有啥根号分治的条件,所以考虑分块。

然后直接对序列分块我也不会在线维护()

然后就会自然有个想法,就是我们维护每次操作加入的 \(r-l+1\)\(x_i\) 会在什么时候全部消失。如果能维护这个,就随便做了。

记最后存在的时间为 \(f_i\),那么 \([i,f_i]\) 时刻就有一个 \(x\) 存在。

我们要想办法求出 \(f_i\)

一个想法是一个个枚举,然后二分,发现还是不会()。

既然都离线了就考虑多个操作一起处理,在这里分块:把每个操作拆成若干个整块和不超过两个散点。

整块操作的出现次数和 \(\le O(m\sqrt{n})\),考虑一次求出一块所有的操作的 \(f_i\),发现此时 \(f\) 满足单调性,所以双指针,这样处理一个块的复杂度是 \(O(q)\) 的,至于维护的过程,出现整块操作打 tag,散点暴力修改就好了,这样均摊以后对所有整块的修改是 \(O(m\sqrt{n})\) 的。

散点恶心一点,考虑枚举点 \(1\)\(n\),记录覆盖它们的散点操作,对于一个点 \(i\) 的两次时间相邻的散点操作还要维护它们之间发生的整块操作个数。然后对每个点双指针就好了。

然后发现我空间被卡了,调块长到 100 然后卡了两三次常数才过...

loj 记录有一页,哈哈,垃圾题,为啥不放到 512M()

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define op(x) ((x&1)?x+1:x-1)
#define odd(x) (x&1)
#define even(x) (!odd(x))
#define lc(x) (x<<1)
#define rc(x) (lc(x)|1)
#define lowbit(x) (x&-x)
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define next Cry_For_theMoon
#define il inline
#define pb(x) push_back(x)
#define is(x) insert(x)
#define sit set<int>::iterator
#define mapit map<int,int>::iterator
#define pi pair<int,int>
#define ppi pair<int,pi>
#define pp pair<pi,pi>
#define fr first
#define se second
#define vit vector<int>::iterator
#define mp(x,y) make_pair(x,y)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;
using namespace std;
const int MAXN=1e5+5,len=100,MAXM=MAXN/len+5;
int n,m,cnt,maxn,a[MAXN];
int L[MAXN],R[MAXN],x[MAXN],die[MAXN];
il int num(int x){return (x-1)/len+1;}
il int S(int x){return (x-1)*len+1;}
il int E(int x){return min(n,x*len);}
vector<pi>col[MAXN],vv;
int occ[MAXM][MAXN],bucket[MAXN],df[MAXN],Len[len+10];
pi op[len+10][MAXN];
void upd(int i,int l,int r,int v){
    maxn=0;
    rep(j,l,r)bucket[j]+=v;
    rep(j,S(i),E(i))maxn=max(maxn,bucket[j]);
}
void solve(int c){
    int maxn=-1;vv.clear();
    for(auto p:col[c]){
        if(p.se>maxn)vv.pb(p);
        maxn=max(maxn,p.se);
    }
    int sz=vv.size();
    rep(j,0,sz-1){
        if(j!=sz-1)vv[j].se=min(vv[j].se,vv[j+1].fr-1);
        df[vv[j].fr]++;df[vv[j].se+1]--;
    }
}
int main(){
//    freopen("q7.in","r",stdin);
//    freopen("out.out","w",stdout);
    scanf("%d%d",&n,&m);rep(i,1,n)scanf("%d",&a[i]);
    rep(i,1,m)scanf("%d%d%d",&L[i],&R[i],&x[i]);
    //散块
    rep(i,1,n){
        if(i==1 || (num(i)!=num(i-1))){
            int idx=num(i),bs=S(idx);
            if(idx-1)rep(j,S(idx-1),E(idx-1)){
                Len[j-S(idx-1)]=0;
            }
            
            rep(j,1,m){
                int l=num(L[j]),r=num(R[j]);
                if(l+1<=idx && idx<=r-1)occ[idx][++occ[idx][0]]=j;
                if(l==r){
                    if(l==idx)rep(k,L[j],R[j])op[k-bs][Len[k-bs]++]=mp(j,occ[l][0]);
                }else{
                    if(l==idx)rep(k,L[j],E(l))op[k-bs][Len[k-bs]++]=mp(j,occ[l][0]);
                    if(r==idx)rep(k,S(r),R[j])op[k-bs][Len[k-bs]++]=mp(j,occ[r][0]);
                }
            }
            
        }
        int bs=S(num(i));
        int sz=Len[i-bs];
        if(!sz)continue;
        int rp=0,cnt=0;
        rep(j,0,sz-1){
            while(rp+1<sz){
                cnt+=(1+op[i-bs][rp+1].se-op[i-bs][rp].se);
                if(cnt<a[i])rp++;
                else{
                    cnt-=(1+op[i-bs][rp+1].se-op[i-bs][rp].se);
                    break;
                }
            }
            int rst=a[i]-cnt-1;
            if(rp+1<sz && rst==op[i-bs][rp+1].se-op[i-bs][rp].se)die[op[i-bs][j].fr]=max(die[op[i-bs][j].fr],op[i-bs][rp+1].fr-1);
            else die[op[i-bs][j].fr]=max(die[op[i-bs][j].fr],(op[i-bs][rp].se+rst>=occ[num(i)][0])?m:(occ[num(i)][op[i-bs][rp].se+rst+1]-1));
            if(j==sz-1)continue;
            if(j==rp)rp++;
            else cnt-=(1+op[i-bs][j+1].se-op[i-bs][j].se);
        }
        
    }  
    //整块
    rep(i,1,num(n)){
        if(!occ[i][0])continue;
        cnt=maxn=0;
        int rp=occ[i][1];
        rep(j,S(i),E(i))bucket[j]=a[j],maxn=max(maxn,bucket[j]);
        rep(j,1,occ[i][0]){
            while(rp+1<=m){
                if(num(L[rp+1])+1<=i && i<=num(R[rp+1])-1)cnt++; 
                if(num(L[rp+1])==num(R[rp+1])){if(num(L[rp+1])==i)upd(i,L[rp+1],R[rp+1],-1);}
                else if(num(L[rp+1])==i)upd(i,L[rp+1],E(i),-1);
                else if(num(R[rp+1])==i)upd(i,S(i),R[rp+1],-1);
                if(maxn>cnt)rp++;
                else{
                    if(num(L[rp+1])+1<=i && i<=num(R[rp+1])-1)cnt--; 
                    if(num(L[rp+1])==num(R[rp+1])){if(num(L[rp+1])==i)upd(i,L[rp+1],R[rp+1],1);}
                    else if(num(L[rp+1])==i)upd(i,L[rp+1],E(i),1);
                    else if(num(R[rp+1])==i)upd(i,S(i),R[rp+1],1);
                    break;
                }
            }
            die[occ[i][j]]=max(die[occ[i][j]],rp);
            if(j==occ[i][0])continue;
            if(rp<occ[i][j+1]){
                cnt=maxn=0;rep(k,S(i),E(i))bucket[k]=a[k],maxn=max(maxn,bucket[k]);
                rp=occ[i][j+1];
            }else{
                rep(rp,occ[i][j],occ[i][j+1]-1){
                    if(num(L[rp+1])+1<=i && i<=num(R[rp+1])-1)cnt--; 
                    if(num(L[rp+1])==num(R[rp+1])){if(num(L[rp+1])==i)upd(i,L[rp+1],R[rp+1],1);}
                    else if(num(L[rp+1])==i)upd(i,L[rp+1],E(i),1);
                    else if(num(R[rp+1])==i)upd(i,S(i),R[rp+1],1);
                }
            }
        }       
    }    
    //统计答案
    rep(i,1,m)col[x[i]].pb(mp(i,die[i]));
    rep(i,1,1e5)solve(i);
    rep(i,1,m)df[i]+=df[i-1];
    rep(i,1,m)printf("%d\n",df[i]);
    return 0;
}
posted on 2022-01-25 15:08  Cry_For_theMoon  阅读(189)  评论(2编辑  收藏  举报