zoukankan      html  css  js  c++  java
  • 【NOI2007】项链工厂 ——老题新做.jpg

    第一次是用 ODT 过的...(虽说跑得飞慢但它就是能过)

    而且还写了发题解...

    第二次是在考场上碰到了这道题,然后居然打了线段树,各种 bug 直接让代码爆零

    但还是补好了代码重新交了一发,发现跑得还可以...

    于是题解也再来一发,不过鉴于 luogu 审题解有点麻烦于是就 cnblogs 上写好了...

    ODT 联动 请点赞谢谢...QWQ

    关于线段树咱其实就是把原来的环破成链,然后维护这个序列,对于旋转和翻转操作打标记,然后其余四种操作都是线段树上询问和维护就能解决了

    然后注意维护的方式就好了,一个是 rotate 要倒着维护以及根据 fl 决定旋转方向,并且对于跨过原端点的区间,我们分成两部分求救,最后合并一下输出就好了

    最最关键的一点,询问整个环的时候原本是有个首位相连颜色是否相同的操作,但如果整个环都是一个颜色就需要特判否则会输出 0

    当然还有线段树别打炸...

    //by Judge
    #include<bits/stdc++.h>
    #define Rg register
    #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
    #define open(S) freopen(S".in","r",stdin),freopen(S".out","w",stdout)
    #define ll long long
    using namespace std;
    const int M=5e5+3;
    typedef int arr[M];
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    char buf[1<<21],*p1,*p2;
    inline int read(){ int x=0,f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-48; return x*f;
    } inline int pread(){ char c=getchar(); while(!isalpha(c)) c=getchar();
    	if(c!='C') return c=='F'?1:(c=='R'?2:(c=='S'?3:4)); c=getchar(); return c=='S'?5:6;
    } char sr[1<<21],z[21]; int Z,C=-1;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    inline void print(int x,char chr='
    '){
    	if(C>1<<20) Ot(); if(x<0) x=-x,sr[++C]='-';
    	while(z[++Z]=x%10+48,x/=10);
    	while(sr[++C]=z[Z],--Z); sr[++C]=chr;
    } int n,q,Ro,Fl; arr a;
    namespace Seg_T{ int tag[M<<2];
    	struct Tr{ int num,L,R; }t[M<<2],ans,ze;
    	#define ls (k<<1)
    	#define rs (k<<1|1)
    	#define lson ls,l,mid
    	#define rson rs,mid+1,r
    	inline Tr merge(Tr x,Tr y){
    		if(!x.num) return y; if(!y.num) return x;
    		return (Tr){x.num+y.num-(x.R==y.L),x.L,y.R};
    	}
    	inline void pushdown(int k){ if(!tag[k]) return ;
    		t[ls]=t[rs]=(Tr){1,tag[k],tag[k]};
    		tag[ls]=tag[rs]=tag[k],tag[k]=0;
    	}
    	void build(int k,int l,int r){ int mid=(l+r)>>1;
    		if(l==r) return t[k]=(Tr){1,a[l],a[l]},void();
    		build(lson),build(rson),t[k]=merge(t[ls],t[rs]);
    	}
    	void update(int k,int l,int r,int L,int R,int c){ int mid=(l+r)>>1;
    		if(l>R||L>r) return ; if(L<=l&&r<=R) return t[k]=(Tr){1,c,c},tag[k]=c,void();
    		pushdown(k); update(lson,L,R,c),update(rson,L,R,c),t[k]=merge(t[ls],t[rs]);
    	}
    	Tr query(int k,int l,int r,int L,int R){ int mid=(l+r)>>1;
    		if(l>R||L>r) return ze; if(L<=l&&r<=R) return t[k];
    		pushdown(k); return merge(query(lson,L,R),query(rson,L,R));
    	}
    	void update_c(int k,int l,int r,int x,int c){ int mid=(l+r)>>1;
    		if(l==r) return t[k]=(Tr){1,c,c},void(); pushdown(k);
    		if(x<=mid) update_c(lson,x,c); else update_c(rson,x,c); t[k]=merge(t[ls],t[rs]);
    	}
    	int query_c(int k,int l,int r,int x){ int mid=(l+r)>>1;
    		if(l==r) return t[k].L; pushdown(k);
    		return x<=mid?query_c(lson,x):query_c(rson,x);
    	}
    } using namespace Seg_T;
    // 对于 R、F 操作,打标记处理。对于剩下的操作线段树上维护 (心情复杂)
    int main(){ int op,x,y,z;
    	n=read(),z=read(),ze.num=0;
    	fp(i,1,n) a[i]=read();
    	build(1,1,n),q=read();
    	while(q--){ op=pread();
    		if(op==1) Fl^=1;
    		else if(op==2){ x=read();
    			if(Fl) Ro=(Ro+x)%n; else Ro=(Ro-x+n)%n;
    		} else if(op==3){ x=read(),y=read();
    			if(Fl) x=(n-x+1)%n+1,y=(n-y+1)%n+1;
    			x=(x+Ro-1)%n+1,y=(y+Ro-1)%n+1;
    			a[x]=query_c(1,1,n,x),a[y]=query_c(1,1,n,y);
    			update_c(1,1,n,x,a[y]),update_c(1,1,n,y,a[x]);
    		} else if(op==4){ x=read(),y=read(),z=read();
    			if(Fl) x=(n-x+1)%n+1,y=(n-y+1)%n+1;
    			x=(x+Ro-1)%n+1,y=(y+Ro-1)%n+1;
    			if(Fl) swap(x,y); 
    			if(x>y) update(1,1,n,x,n,z),update(1,1,n,1,y,z);
    			else update(1,1,n,x,y,z);
    		} else if(op==5){ x=read(),y=read();
    			if(Fl) x=(n-x+1)%n+1,y=(n-y+1)%n+1;
    			x=(x+Ro-1)%n+1,y=(y+Ro-1)%n+1;
    			if(Fl) swap(x,y); 
    			if(x>y) ans=merge(query(1,1,n,x,n),query(1,1,n,1,y));
    			else ans=query(1,1,n,x,y); print(max(ans.num,1));
    		} else print(max(t[1].num-(t[1].L==t[1].R),1));
    	} return Ot(),0;
    }
    
  • 相关阅读:
    十年经验手把手教你选购翡翠
    眼睛视力
    玻璃
    前端小技巧
    儿童牙齿矫正
    MySQL的JDBC驱动源码解析
    书海杂谈
    电子设备
    股市国家队
    影视
  • 原文地址:https://www.cnblogs.com/Judge/p/11626346.html
Copyright © 2011-2022 走看看