1. 程式人生 > 其它 >720--詞典中最長的單詞(字典樹)

720--詞典中最長的單詞(字典樹)

題面傳送門
題目中怎麼不說明這個可以取空區間啊害我調半天。
這個重複的算一次就容易想到區間數顏色的相關套路,就是每個點記錄前面最近的點。
離線詢問然後掃描線,記錄線段樹上每個位置的值為到當前點的區間的和,那麼需要做的就是兩種操作:
將上一個這個數的出現位置+1到現在的位置都加上一個數。
查詢區間歷史最值。
歷史最值有基本套路,新加一個權值\(F_i\)表示\(i\)位置的歷史最值,那麼每次掃描完一個數以後就對於全序列讓\(F_i=\max(F_i,A_i)\)
這個維護一個標記,再配合一個位移標記就可以和加法相容了。
時間複雜度線段樹的\(O(n\log n)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N (100000+5)
#define M (1000000+5)
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;const ll INF=1e18;
int n,m,k,x,y;ll Ans[N],A[N];map<ll,int> F;struct Ques{int x,id;};vector<Ques> Q[N+5];
namespace Tree{
	#define ls now<<1
	#define rs now<<1|1
	int Fl[N+5<<2];ll W[N+5<<2],G[N+5<<2],F[N+5<<2],H[N+5<<2];I void Up(int now){F[now]=max(F[ls],F[rs]);G[now]=max(G[ls],G[rs]);}
	I void PL(int now,ll w){Fl[now]?(W[now]=max(W[now],w)):(Fl[now]=1,W[now]=w);G[now]=max(G[now],F[now]+W[now]);}I void PH(int now,ll w){H[now]+=w;F[now]+=w;Fl[now]&&(W[now]-=w);}
	I void P(int now){H[now]&&(PH(ls,H[now]),PH(rs,H[now]),H[now]=0);Fl[now]&&(PL(ls,W[now]),PL(rs,W[now]),Fl[now]=W[now]=0);}
	I ll Qry(int x,int y,int l=1,int r=n,int now=1){if(x<=l&&r<=y) return G[now];P(now);int m=l+r>>1;ll F1=-INF,F2=-INF;x<=m&&(F1=Qry(x,y,l,m,ls));y>m&&(F2=Qry(x,y,m+1,r,rs));return max(F1,F2);}
	I void Ins(int x,int y,ll w,int l=1,int r=n,int now=1){if(x<=l&&r<=y) return PH(now,w);int m=l+r>>1;P(now);x<=m&&(Ins(x,y,w,l,m,ls),0);y>m&&(Ins(x,y,w,m+1,r,rs),0);Up(now);}
	I void Add(int x,int y,int l=1,int r=n,int now=1){if(x<=l&&r<=y) return PL(now,0);int m=l+r>>1;P(now);x<=m&&(Add(x,y,l,m,ls),0);y>m&&(Add(x,y,m+1,r,rs),0);Up(now);}
}
int main(){
	freopen("1.in","r",stdin);
	RI i;scanf("%d",&n);for(i=1;i<=n;i++) scanf("%lld",&A[i]);scanf("%d",&m);for(i=1;i<=m;i++) scanf("%d%d",&x,&y),Q[y].PB((Ques){x,i});
	for(i=1;i<=n;i++) {Tree::Ins(F[A[i]]+1,i,A[i]);F[A[i]]=i;Tree::Add(1,n);for(Ques d:Q[i]) Ans[d.id]=Tree::Qry(d.x,i);}for(i=1;i<=m;i++) printf("%lld\n",Ans[i]);
}