zoukankan      html  css  js  c++  java
  • BZOJ4447: [Scoi2015]小凸解密码

    这题怎么这么难读懂……而且还读错了一次……mhy的游记里写的他写的二分+线段树,然后还说可以用set,表示非常懵逼……我只会线段树暴搞,维护到左右端点的最远和次远的0区间,查询分别查左右两半的答案,再设法合并……跑得巨慢……

    UPD:确实用set维护一下所有0区间就好了……我怎么想出来这个线段树的……脑抽系列……

    #include<algorithm>
    #include<cstdio>
    #define I (J+1)
    #define J (i+j>>1)
    #define P (k<<1)
    #define S (P^1)
    using namespace std;
    const int N=1e5+5;
    int n,m,s,t,a[N];
    char c[N];
    struct node{
    	int x,y,z,s1,s2,t1,t2;
    	void pre(int i){
    		x=y=i,z=1,s1=t1=i?-1:0,s2=t2=-1;
    	}
    }f[N*8];
    node operator+(node a,node b){
    	node c={a.x,b.y,a.z+b.z};
    	int j=a.y||b.x?-1:0;
    	if(b.s1==j)c.s1=a.s1,c.s2=a.s2;
    	else
    		c.s1=b.s1+a.z,c.s2=b.s2!=j?b.s2+a.z:a.s1;
    	if(a.t1==j)c.t1=b.t1,c.t2=b.t2;
    	else
    		c.t1=a.t1+b.z,c.t2=a.t2!=j?a.t2+b.z:b.t1;
    	return c;
    }
    int cal(int i){
    	int s=i%n,t=(s+n-1)%n;
    	if(c[s]=='+')
    		return(a[s]+a[t])%10;
    	return(a[s]*a[t])%10;
    }
    void pre(int i,int j,int k){
    	if(i==j)f[k].pre(cal(i));
    	else
    		pre(i,J,P),pre(I,j,S),f[k]=f[P]+f[S];
    }
    void vary(int s,int t,int i,int j,int k){
    	if(i==j)f[k].pre(t);
    	else{
    		if(s<I)vary(s,t,i,J,P);
    		if(s>J)vary(s,t,I,j,S);
    		f[k]=f[P]+f[S];
    	}
    }
    node ask(int s,int t,int i,int j,int k){
    	if(s==i&&j==t)return f[k];
    	if(t<I)return ask(s,t,i,J,P);
    	if(s>J)return ask(s,t,I,j,S);
    	return ask(s,J,i,J,P)+ask(I,t,I,j,S);
    }
    void vary(int s,int t){vary(s,t,0,n*2-1,1);}
    node ask(int s,int t){return ask(s,t,0,n*2-1,1);}
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<n;++i)
    		scanf("%d %c",a+i,c+i);
    	pre(0,n*2-1,1);
    	while(m--){
    		scanf("%d%d",&s,&t);
    		if(s==1){
    			scanf("%d %c",a+t,c+t);
    			vary(t,cal(t));
    			vary(t+n,cal(t));
    			vary(t+1,cal(t+1));
    			if(t!=n-1)
    				vary(t+n+1,cal(t+1));
    		}else{
    			vary(t,a[t]);
    			node a=ask(t,t+(n-1)/2),b=ask(t+(n+1)/2,t+n-1);
    			if(~b.t1&&(a.x||b.t1))++b.t1;
    			if(~b.t2&&(a.x||b.t2))++b.t2;
    			printf("%d
    ",a.y||b.x?max(a.s1,b.t1):max(max(a.s2,b.t2),min(a.s1,b.t1)));
    			vary(t,cal(t));
    		}
    	}
    }
    
  • 相关阅读:
    易股(私募) 笔试
    TinyWS
    重载 隐藏 重写(覆盖)
    vector emplace_back() 和push_back() 的区别
    std::ref 和 std::cref 的使用
    网络 I/O复用模式之select、poll、epoll
    网络I/O中 同步/异步 阻塞/非阻塞 概念
    git 使用方法 (reset merge rebase stash diff等)
    C++11 thread用法
    C++中 锁的使用 互斥锁:std::mutex std::lock_guard std::unique_lock ,读写锁使用shared_mutex ,条件变量使用std::condition_variable类
  • 原文地址:https://www.cnblogs.com/f321dd/p/6403097.html
Copyright © 2011-2022 走看看