• CF217E Alien DNA


    Solution

    因为后面的操作不会对前面的操作有影响,所以我们考虑把操作倒过来。相应的,一开始就只有 \(k\) 个位置有效,然后对于操作 \([l,r]\) ,就把 \([r+1,r+(r-l+1)]\)\([1,k]\) 的交集标记为已操作,并记录每一位是哪一位转移过来的。然后对于前一个操作,只用修改那些未标记的位置。

    最多有 \(k\) 位,所以最多只要 \(k\) 次。具体记录位置可以用线段树+二分来寻找。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ls o<<1
    #define rs o<<1|1
    using namespace std;
    
    const int N = 3e6 + 10;
    int k, n, l[N], r[N], tr[N * 4], f[N];
    char s[N], ans[N];
    
    void build(int o,int l,int r){
    	tr[o]=r-l+1;
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    }
    
    int find(int o,int l,int r,int k,int p){
    	while(l!=r){
    		tr[o]-=p;
    		int mid=(l+r)>>1;
    		if(tr[ls]>=k) r=mid,o<<=1;
    		else k-=tr[ls],o=rs,l=mid+1;
    	}
    	tr[o]-=p;
    	return l;
    }
    
    void work(){
    	for(int i=n;i>=1;i--){
    		if(r[i]>=tr[1]) continue;
    		int t=l[i]&1^1;
    		int now=l[i]+t;
    		if(now>r[i]) now=l[i]+(t^1);
    		for(int j=1;j<=r[i]-l[i]+1&&r[i]<tr[1];j++){
    			int p=find(1,1,k,r[i]+1,1);
    			f[p]=find(1,1,k,now,0);
    			now+=2;
    			if(now>r[i]) now=l[i]+(t^1);
    		}
    	}
    	for(int i=1,j=1;i<=k;i++)
    		if(f[i]) ans[i]=ans[f[i]];
    		else ans[i]=s[j++];
    	puts(ans+1);
    }
    
    int main(){
    	gets(s+1);
    	scanf("%d%d",&k,&n);
    	build(1,1,k);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&l[i],&r[i]);
    	work();
    	return 0;
    }
    
  • 相关阅读:
    Codeforces 787B. Not Afraid
    Codeforces 670D. Magic Powder
    POJ 1979 Red and Black
    T1215:迷宫
    POJ 1163 The Triangle
    洛谷P1219 八皇后
    T1212:LETTERS
    T1317:【例5.2】组合的输出
    洛谷P1706 全排列问题
    codevs 5971 打击犯罪
  • 原文地址:https://www.cnblogs.com/jasony/p/13587625.html
Copyright © 2020-2023  润新知