国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[SD2016集訓]Play with array(分塊+雙向鏈表)

2019-11-08 19:55:26
字體:
來源:轉載
供稿:網友

題目描述

這里寫圖片描述 這里寫圖片描述

題解

PRe+nxt=雙向鏈表,哦哦漲姿勢了。。。 這題faebdc的solution說是要用塊鏈做,不過塊鏈常數巨巨巨大,感覺分塊+重構更科學

對序列分塊了之后對每一個塊維護數i出現了多少次,整塊直接查詢剩余暴力 關鍵是有移動的操作,并且需要重新編號,所以元素與元素之間、塊與塊之間都可以用雙向鏈表來維護 尋找第lr個元素利用維護塊的大小實現O(n√)查詢 移動的話就直接將第r個元素移動到l的前面,和l并到一個塊里O(1) 注意移動了之后元素的鏈表需要修改,塊的左右指針需要修改,并且如果一個塊被刪空了塊的鏈表也需要修改 移動次數太多之后會導致查詢效率下降,所以過一段時間要重構一下 不過這題數據弱得很,不重構似乎也是可以過的

代碼

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 100005#define T 350int n,m,opt,l,r,k,block,t,ans;int a[N],b[N],pre[N],nxt[N],num[N];struct data{ int sz,pre,nxt,l,r; int cnt[N];}bl[T];void build(){ for (int i=1;i<=n;++i) { pre[i]=i-1,nxt[i]=i+1; num[i]=(i-1)/block+1; ++bl[num[i]].cnt[a[i]]; } bl[1].l=1,bl[1].r=block,bl[1].nxt=2,bl[1].sz=block; for (int i=2;i<=t;++i) { bl[i].l=bl[i-1].l+block,bl[i].r=bl[i-1].r+block; bl[i].pre=i-1,bl[i].nxt=i+1,bl[i].sz=block; }bl[t].r=n,bl[t].sz=n-bl[t].l+1;}int find(int x){ int now=1,size=0; while (size+bl[now].sz<x) size+=bl[now].sz,now=bl[now].nxt; int pt=bl[now].l; for (int i=size+1;i<x;++i) pt=nxt[pt]; return pt;}void change(int l,int r){ l=find(l),r=find(r); int numl=num[l],numr=num[r],val=a[r]; if (numl==numr) { if (bl[numl].l==l) bl[numl].l=r; if (bl[numr].r==r) bl[numr].r=pre[bl[numr].r]; nxt[pre[r]]=nxt[r]; pre[nxt[r]]=pre[r]; pre[r]=pre[l];nxt[r]=l; nxt[pre[l]]=pre[l]=r; } else { if (bl[numl].l==l) bl[numl].l=r; if (bl[numr].r==r) bl[numr].r=pre[r]; if (bl[numr].l==r) bl[numr].l=nxt[r]; nxt[pre[r]]=nxt[r]; pre[nxt[r]]=pre[r]; pre[r]=pre[l];nxt[r]=l; nxt[pre[l]]=pre[l]=r; --bl[numr].sz;++bl[numl].sz; if (!bl[numr].sz) { bl[bl[numr].pre].nxt=bl[numr].nxt; bl[bl[numr].nxt].pre=bl[numr].pre; } --bl[numr].cnt[val];++bl[numl].cnt[val]; num[r]=numl; }}void query(int l,int r,int k){ l=find(l),r=find(r); int numl=num[l],numr=num[r]; if (numl==numr) { for (int i=l;;i=nxt[i]) { if (a[i]==k) ++ans; if (i==r) break; } return; } if (l==bl[numl].l) l=numl; else { for (int i=l;;i=nxt[i]) { if (a[i]==k) ++ans; if (i==bl[numl].r) break; } l=bl[numl].nxt; } if (r==bl[numr].r) r=numr; else { for (int i=r;;i=pre[i]) { if (a[i]==k) ++ans; if (i==bl[numr].l) break; } r=bl[numr].pre; } for (int i=l;i<=r;i=bl[i].nxt) ans+=bl[i].cnt[k];}void rebuild(){ int now=0; for (int i=bl[1].l;now<=n;i=nxt[i]) b[++now]=a[i]; for (int i=1;i<=n;++i) a[i]=b[i]; memset(bl,0,sizeof(bl)); build();}int main(){ freopen("array.in","r",stdin); freopen("array.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d",&a[i]); block=sqrt(n);t=(n-1)/block+1; build(); scanf("%d",&m); for (int i=1;i<=m;++i) { scanf("%d",&opt); if (opt==1) { scanf("%d%d",&l,&r); if (l>r) swap(l,r); if (l==r) continue; change(l,r); } else { scanf("%d%d%d",&l,&r,&k); if (l>r) swap(l,r); ans=0;query(l,r,k); printf("%d/n",ans); } if (i%20000==0) rebuild(); }}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 福清市| 集安市| 五大连池市| 陇西县| 邯郸县| 徐水县| 天峻县| 达州市| 成安县| 侯马市| 东山县| 清流县| 缙云县| 永泰县| 城步| 德昌县| 蓬溪县| 定远县| 扬中市| 白河县| 墨江| 忻城县| 阳曲县| 彰化市| 宜章县| 贵南县| 广德县| 凭祥市| 浪卡子县| 延安市| 饶平县| 武平县| 承德县| 遵化市| 万山特区| 沛县| 桂阳县| 衡南县| 保靖县| 晋州市| 礼泉县|