• [CC-SEINC]Sereja and Subsegment Increasings


    [CC-SEINC]Sereja and Subsegment Increasings

    题目大意:

    有长度为(n(nle10^5))的序列(A)(B)

    在一次操作中,可以选择一个区间增加(1)

    求让(A)(B)在模(4)意义下相等,至少要对(A)执行多少次操作。

    思路:

    (A,B)对应作差,(C_i=B_i-A_i)

    (C)的查分(D_i=C_i-C_{i+1})

    如果不考虑模(4),答案即为(summax(D_i,0))

    而模(4)相当于可以对(C)区间加(4),对应到(D)上就是对于区间((l,r])(D_l+=4,D_r-=4)

    考虑怎样选择区间能够使答案更优。

    对于区间((l,r]),考虑以下情况:

    1. (D_l=2,D_r=-3),会使答案(-1)
    2. (D_l=3,D_r=-2),会使答案(-1)
    3. (D_l=3,D_r=-3),会使答案(-2)

    而其余情况都不会使答案更优。

    因此可以线性扫一遍,记录(2,3)出现的次数,将当前点作为右端点时择优更新答案即可。

    时间复杂度(mathcal O(n))

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=1e5+1;
    int a[N];
    int main() {
    	for(register int T=getint();T;T--) {
    		const int n=getint();
    		for(register int i=1;i<=n;i++) a[i]=getint();
    		for(register int i=1;i<=n;i++) {
    			a[i]=(getint()-a[i]+4)%4;
    		}
    		int ans=a[n],cnt2=0,cnt3=0;
    		for(register int i=1;i<n;i++) {
    			a[i]-=a[i+1];
    			ans+=std::max(0,a[i]);
    		}
    		for(register int i=1;i<=n;i++) {
    			if(a[i]==2) cnt2++;
    			if(a[i]==3) cnt3++;
    			if(a[i]==-2) {
    				if(cnt3) {
    					cnt2++;
    					cnt3--;
    					ans--;
    				}
    			}
    			if(a[i]==-3) {
    				if(cnt3) {
    					cnt3--;
    					ans-=2;
    				} else if(cnt2) {
    					cnt2--;
    					ans--;
    				}
    			}
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    git配置公钥,私钥
    vscode之vue文件代码格式化代码无效解决办法
    [python 并行3]进程
    [spring 并行6]分布式
    [spring 并行5]GPU
    [python 并行2]线程
    [spring 并行4]异步
    [python 并行1]简介
    [flask] flask api + vue 跨域问题
    [spring学习4] MVC
  • 原文地址:https://www.cnblogs.com/skylee03/p/9497126.html
Copyright © 2020-2023  润新知