#權值線段樹#洛谷 3939 數顏色
阿新 • • 發佈:2020-09-19
分析
考慮按照顏色建權值線段樹,交換直接刪除再新增就可以了
如果離散化要特判不過其實不需要離散化
程式碼
#include <cstdio> #include <cctype> #define rr register using namespace std; const int N=300011; int n,Q,w[N<<5],ls[N<<5],cnt,rs[N<<5],rt[N],a[N]; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void print(int ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } inline void update(int &k,int l,int r,int x,int y){ if (!k) k=++cnt; w[k]+=y; if (l==r) return; rr int mid=(l+r)>>1; if (x<=mid) update(ls[k],l,mid,x,y); else update(rs[k],mid+1,r,x,y); } inline signed query(int k,int l,int r,int x,int y){ if (!k) return 0; if (l==x&&r==y) return w[k]; rr int mid=(l+r)>>1; if (y<=mid) return query(ls[k],l,mid,x,y); else if (x>mid) return query(rs[k],mid+1,r,x,y); else return query(ls[k],l,mid,x,mid)+query(rs[k],mid+1,r,mid+1,y); } signed main(){ n=iut(); Q=iut(); for (rr int i=1;i<=n;++i) update(rt[a[i]=iut()],1,n,i,1); while (Q--){ rr int o=iut(); if (o==1){ rr int l=iut(),r=iut(),z=iut(); print(query(rt[z],1,n,l,r)),putchar(10); }else{ rr int x=iut(); if (a[x]==a[x+1]) continue; update(rt[a[x]],1,n,x,-1); update(rt[a[x+1]],1,n,x+1,-1); update(rt[a[x]],1,n,x+1,1); update(rt[a[x+1]],1,n,x,1); a[x]^=a[x+1],a[x+1]^=a[x],a[x]^=a[x+1]; } } return 0; }