日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

P4130,jzoj1214-[NOI2007]项链工厂【线段树】

發(fā)布時(shí)間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P4130,jzoj1214-[NOI2007]项链工厂【线段树】 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

正題

題目鏈接:https://www.luogu.org/problemnew/show/P4130


題目大意

一個(gè)環(huán)形顏色珠子鏈,位置(注意不是上面的珠子)從最上順時(shí)針下來(lái)位置依次標(biāo)號(hào)1~n1\sim n1n。

然后要求支持以下操作

  • Rk:R\ k:R?k:將所有珠子順時(shí)針旋轉(zhuǎn)kkk個(gè)。
  • F:F:F:將所有珠子以111向下翻轉(zhuǎn)
  • Sij:S\ i\ j:S?i?j:交換iiijjj上的珠子
  • Pijk:P\ i\ j\ k:P?i?j?k:iii順時(shí)針到jjj的珠子都涂上顏色kkk
  • C:C:C:詢問(wèn)整個(gè)鏈有多少顏色段
  • CSij:CS\ i\ j:CS?i?j:詢問(wèn)iii順時(shí)針到jjj有多少顏色段。
  • (顏色段為連續(xù)的相同顏色)


    解題思路

    先不考慮前兩個(gè)操作,我們可以用線段樹(shù)進(jìn)行操作。

    儲(chǔ)存[l,r,w,lc,rc,lazy][l,r,w,lc,rc,lazy][l,r,w,lc,rc,lazy]分別表示下標(biāo)l~rl\sim rlr,有www個(gè)顏色段,頭顏色為lclclc,尾顏色為rcrcrc,懶惰標(biāo)簽lazylazylazy

    然后我們可以利用lc,rclc,rclc,rc進(jìn)行合并。

    之后我們就可以輕易的實(shí)現(xiàn)后4個(gè)操作。

    那我們考慮前兩個(gè)操作,我們會(huì)發(fā)現(xiàn)它并不會(huì)破壞連續(xù)性,也就是任何一個(gè)位置相鄰的兩個(gè)位置的數(shù)字編號(hào)也與其相鄰。

    那么我們就可以使用一個(gè)十分優(yōu)秀的算法,我們用ttt記錄其旋轉(zhuǎn)了幾步,然后用BBB記錄是否翻轉(zhuǎn)(因?yàn)榉D(zhuǎn)兩次等于沒(méi)有翻轉(zhuǎn))。之后就可以計(jì)算出給出的數(shù)字段旋轉(zhuǎn)和翻轉(zhuǎn)之前應(yīng)該在哪個(gè)位置。
    然后照樣計(jì)算就好了。


    codecodecode

    #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=500100; struct Tree_node{int l,r,w,lc,rc,lazy; }ans; int n,C,m,t,B; struct Line_cut_tree{Tree_node t[N<<2]; // node merge(node tl,node tr) // { // node t; // t.w=tl.w+tr.w+(tl.rc!=tr.lc); // return t; // }void megre(Tree_node &t,Tree_node tl,Tree_node tr){t.lc=tl.lc;t.rc=tr.rc;t.w=tl.w+tr.w-(tl.rc==tr.lc);}void build(int x,int l,int r){t[x].l=l;t[x].r=r;if(l==r){scanf("%d",&t[x].lc); t[x].rc=t[x].lc;t[x].w=1;return;}int mid=(l+r)/2;build(x*2,l,mid);build(x*2+1,mid+1,r);megre(t[x],t[x*2],t[x*2+1]);}void downdata(int x){if(!t[x].lazy) return;t[x*2].lazy=t[x*2+1].lazy=t[x].lazy;t[x*2].w=t[x*2+1].w=1;t[x*2].lc=t[x*2].rc=t[x*2+1].lc=t[x*2+1].rc=t[x].lazy;t[x].lazy=0;}void Ask(int x,int l,int r){if(t[x].l==l&&t[x].r==r){if(!ans.rc) ans.lc=t[x].lc;megre(ans,ans,t[x]);return;}downdata(x);if(r<=t[x*2].r) Ask(x*2,l,r);else if(l>t[x*2].r) Ask(x*2+1,l,r);else Ask(x*2,l,t[x*2].r),Ask(x*2+1,t[x*2+1].l,r);megre(t[x],t[x*2],t[x*2+1]);}void Change(int x,int l,int r,int z){if(t[x].l==l&&t[x].r==r){t[x].w=1;t[x].lazy=t[x].rc=t[x].lc=z;return;}downdata(x);if(r<=t[x*2].r) Change(x*2,l,r,z);else if(l>t[x*2].r) Change(x*2+1,l,r,z);else Change(x*2,l,t[x*2].r,z),Change(x*2+1,t[x*2+1].l,r,z);megre(t[x],t[x*2],t[x*2+1]);} }Tree; void Reset() {ans.w=ans.rc=0;} void doing(int &x,int &y) {if(!B){if(x>=t+1) x=x-t;else x=n-t+x;if(y>=t+1) y=y-t;else y=n-t+y;}else{if(x<=t+1) x=t-x+2;else x=t+n-x+2;if(y<=t+1) y=t-y+2;else y=t+n-y+2;swap(x,y);} } int main() {scanf("%d%d",&n,&C);Tree.build(1,1,n);scanf("%d",&m);for(int i=1;i<=m;i++){char op[3];scanf("%s",op);if(op[0]=='C'){if(op[1]=='S'){int x,y;scanf("%d%d",&x,&y);if(x==y)x++,x--;doing(x,y);if(y>=x) Reset(),Tree.Ask(1,x,y);else {Tree_node a1,a2;Reset();Tree.Ask(1,x,n);a1=ans;Reset();Tree.Ask(1,1,y);a2=ans;if(B){swap(a1.lc,a1.rc);swap(a2.lc,a2.rc);swap(a1,a2);}Tree.megre(ans,a1,a2);}printf("%d\n",ans.w);}elseprintf("%d\n",max(Tree.t[1].w-(Tree.t[1].lc==Tree.t[1].rc),1));}else if(op[0]=='R'){int k;scanf("%d",&k);t=(t+k)%n;}else if(op[0]=='F') B^=1,t=n-t;else if(op[0]=='S'){int x,y;scanf("%d%d",&x,&y);doing(x,y);Reset();Tree.Ask(1,x,x);int a1=ans.lc;Reset();Tree.Ask(1,y,y);int a2=ans.lc;Tree.Change(1,x,x,a2);Tree.Change(1,y,y,a1);}else if(op[0]=='P'){int x,y,z;scanf("%d%d%d",&x,&y,&z);doing(x,y);if(y>=x) Tree.Change(1,x,y,z);else Tree.Change(1,x,n,z),Tree.Change(1,1,y,z);}} }

    總結(jié)

    以上是生活随笔為你收集整理的P4130,jzoj1214-[NOI2007]项链工厂【线段树】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。