zoukankan      html  css  js  c++  java
  • P4130 [NOI2007]项链工厂

    间隙

    大致题意

    给一个串包含(n)个珠子的项链,其中第(i)个珠子的颜色是(c_i)

    现在要求维护以下几个操作:

    (n,m≤500000)

    分析

    细节巨多的一道线段树题

    调了将近四个小时/kk

    如果没有翻转操作,这就是个线段树裸题

    不难发现,翻转操作只是把顺时针旋转变成了逆时针旋转

    维护两个变量(r)(k),分别代表旋转的幅度和是否翻转,然后就可以通过计算轻松搞出查询区间了

    亿点细节

    • 区间颜色全部相同时要特判

    • 旋转后区间要翻转

    • 注意题目中给的是一个环,因此要特判(l≤r)(l>r)的情况

    • 区间赋值相加tag,傻逼!

    • 交换操作用原数列数据,傻逼!

    using namespace std;
    const int MAXN = 500010;
    #define lson node<<1
    #define rson node<<1|1 
    inline int read(){
    	int X=0; bool flag=1; char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
    	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
    	if(flag) return X;
    	return ~(X-1);
    }
    int n,m,a[MAXN];
    int now;
    int T[MAXN];
    int cnt = 0;
    bool is_rotate;
    struct st{
    	int l,r,val,tag;
    }tree[MAXN<<2];
    stack<st> s;
    void pushdown(int node){
    	if(!tree[node].tag) return;
    	tree[lson].l = tree[lson].r = tree[rson].l = tree[rson].r = tree[node].tag;
    	tree[lson].tag = tree[node].tag;
    	tree[rson].tag = tree[node].tag;
    	tree[lson].val = tree[rson].val = 1;
    	tree[node].tag = 0;
    }
    void pushup(int node){
    	tree[node].l = tree[lson].l;
    	tree[node].r = tree[rson].r;
    	if(tree[lson].r == tree[rson].l){
    		tree[node].val = tree[lson].val+tree[rson].val -1;
    	}
    	else tree[node].val = tree[lson].val+tree[rson].val;
    }
    void build(int node,int l,int r){
    	if(l==r){
    		tree[node].l = tree[node].r = a[l];
    		tree[node].val = 1;
    		return;
    	}
    	int mid = (l+r)>>1;
    	build(lson,l,mid);
    	build(rson,mid+1,r);
    	pushup(node);
    }
    int query(int node,int l,int r,int x,int y){
    	if(x<=l&&y>=r){
    		return tree[node].val;
    	}
    	pushdown(node);
    	int mid = (l+r)>>1;
    	if(x<=mid&&y>mid) return query(lson,l,mid,x,y)+query(rson,mid+1,r,x,y)-(tree[lson].r==tree[rson].l);
    	if(x<=mid) return query(lson,l,mid,x,y);
    	if(y>mid) return query(rson,mid+1,r,x,y);
    	pushup(node);
    }
    st find(int node,int l,int r,int x,int y){
    	if(x<=l&&y>=r){
    		return tree[node];
    	}
    	pushdown(node);
    	int mid = (l+r)>>1;
    	if(x<=mid) return find(lson,l,mid,x,y);
    	if(y>mid) return find(rson,mid+1,r,x,y);
    	
    }
    
    /*int merge2(){
    	int ans = 0;
    	st last;
    	while(!s.empty()){
    		st a = s.top();
    		s.pop();
    		ans+=a.val;
    		if(a.l==last.r) ans--;
    		last = a;
    		//cout<<"["<<a.l<<" "<<a.r<<"]"<<" "<<a.val<<" ";
    	}
    	return ans;
    }*/
    void modify(int node,int l,int r,int x,int y,int val){
    	if(x<=l&&y>=r){
    		tree[node].val = 1;
    		tree[node].tag = val;
    		tree[node].l = tree[node].r = val;
    		return;
    	}
    	pushdown(node);
    	int mid = (l+r)>>1;
    	if(x<=mid) modify(lson,l,mid,x,y,val);
    	if(y>mid) modify(rson,mid+1,r,x,y,val);
    	pushup(node);
    }
    
    void calc(int &x,int &y){
    	if(!is_rotate)
        {
            if(x>=now+1)x=x-now;
            else x=n-now+x;
            if(y>=now+1) y=y-now;
            else y=n-now+y;
        }else
        {
            if(x<=now+1)x=now-x+2;
            else x=now+n-x+2;
            if(y<=now+1) y=now-y+2;
            else y=now+n-y+2;
        }
    } 
    int main(){
    	n = read(),m = read();
    	for(int i=1;i<=n;i++) a[i] = read();
        build(1,1,n);
        int t;
        t = read();
        while(t--){
        	char opt[2];
        	cin>>opt;
        	if(opt[0]=='R'){
        		int k = read();
        		now = (now+k)%n;
    		}
    		else if(opt[0]=='F'){
    			is_rotate = !is_rotate;
    			now = (n-now)%n;
    		}
    		else if(opt[0]=='P'){
    			int l = read(),r = read(),val = read();
    			calc(l,r);
    			if(is_rotate) swap(l,r);
    			if(l<=r) modify(1,1,n,l,r,val);
    			else modify(1,1,n,l,n,val),modify(1,1,n,1,r,val);
    		}
    		else if(opt[0]=='C'&&opt[1]!='S'){
    			if(tree[1].l!=tree[1].r) cout<<tree[1].val<<endl;//T[++cnt] = tree[1].val;
    			else cout<<max(1,tree[1].val - 1)<<endl;//T[++cnt] = tree[1].val-1;
    		}
    		else if(opt[0]=='S'){
    			int l =read(),r = read();
    			calc(l,r);
    			st a = find(1,1,n,l,l);
    			st b = find(1,1,n,r,r);
    			modify(1,1,n,l,l,b.l);
    			modify(1,1,n,r,r,a.l);
    
    		}
    		else{
    			int l = read(),r = read();
    			calc(l,r);
    			if(is_rotate) swap(l,r);
    			//cout<<"["<<l<<" "<<r<<"]"<<endl;
    			if(l<=r) cout<<query(1,1,n,l,r)<<endl;
    			else{
    				cout<<max(1,query(1,1,n,l,n)+query(1,1,n,1,r)-(tree[1].l==tree[1].r))<<endl; 
    			}
    			 // T[++cnt] = merge();
    		}
    	}
    	
    }
    
  • 相关阅读:
    TextVew中文空格
    java中String字符串的替换函数:replace与replaceAll的区别
    朝花夕拾
    Eclipse启动时卡死在"Android SDK: Resolving error markers"的解决方法
    签名“未签名”apk文件命令
    TODO
    完全卸载AndroidStudio
    Gradle
    经受时间沉淀的15 个 Android 通用流行框架大全
    jquery 获取 新添加元素 点击后 的子元素
  • 原文地址:https://www.cnblogs.com/xcxc82/p/14013498.html
Copyright © 2011-2022 走看看