zoukankan      html  css  js  c++  java
  • Codeforces Round #741

    ( ext{Rings})

    解法

    先开始想了一堆杂七杂八的情况,但实际上一个 (0) 就够了…

    • 串中没有 (0)。直接选 1 n-1 2 n
    • 有在 (iin[1,n/2]) 中的 (0)。选 i n i+1 n
    • 有在 (iin[n/2+1,n]) 中的 (0)。选 1 i 1 i-1

    ( ext{Two Hundred Twenty One})

    解法

    观察样例我们可以发现答案只有 (0,1,2)。预处理前缀和 (pre_i)。考虑最终序列长度一定是偶数,我们不妨做出以下猜想:

    • (pre_r-pre_{l-1}=0)。这个其实也不用猜也知道答案是 (0)
    • 长度为偶数。答案是 (2)。而且这也是答案最小的情况。
    • 长度为奇数。答案是 (1)。而且这也是答案最小的情况。

    长度为偶数的序列随便删一个就是奇数的情况,所以我们只用证明长度为奇数答案是 (1) 即可。

    由于删掉一个数后,它后面的和会取相反数,所以问题转化为能否找到一个数,它左右两边的和相等。

    (s=pre_r-pre_{l-1})。如果删掉的数 贡献(1),我们希望它左边的和是 (frac{s-1}{2});如果删掉的数 贡献(-1),我们希望它左边的和是 (frac{s+1}{2})。而这两个数在 (0)(s) 之间,且一个数只会让序列和变化 (1)(-1),所以必定是有解的。

    如何构造长度为奇数的答案?用 g[0/1][V] 存储贡献为 (1)(-1),前缀和到这一位是 (V) 的所有 (i)。对于每个询问在对应的 vector 里二分即可。需要注意实现时这两个数最好用整除,不然可能会出现 (mathtt{qqgg}) 的问题。

    代码

    #include <cstdio>
    #define print(x,y) write(x),putchar(y)
    
    template <class T>
    inline T read(const T sample) {
    	T x=0; char s; bool f=0;
    	while((s=getchar())>'9' or s<'0')
    		f|=(s=='-');
    	while(s>='0' and s<='9')
    		x=(x<<1)+(x<<3)+(s^48),
    		s=getchar();
    	return f?-x:x;
    }
    
    template <class T>
    inline void write(const T x) {
    	if(x<0) {
    		putchar('-'),write(-x);
    		return;
    	}
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    }
    
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const int maxn=3e5;
    
    int n,q,pre[maxn+2];
    char s[maxn+3];
    vector <int> g[2][(maxn<<1)+5];
    vector <int> :: iterator it;
    
    void calc(int x,int y) {
    	int s=pre[y]-pre[x-1];
    	int r=(s-1>>1)+pre[x-1]+1;
    	it=lower_bound(g[0][r+maxn].begin(),g[0][r+maxn].end(),x);
    	if(it!=g[0][r+maxn].end() and *it<=y)
    		return (void)(print(*it,'
    '));
    	r=(s+1>>1)+pre[x-1]-1;
    	it=lower_bound(g[1][r+maxn].begin(),g[1][r+maxn].end(),x);
    	if(it!=g[1][r+maxn].end() and *it<=y)
    		return (void)(print(*it,'
    '));
    }
    
    int main() {
    	for(int T=read(9);T;--T) {
    		n=read(9),q=read(9);
    		scanf("%s",s+1);
    		for(int i=1;i<=n;++i) {
    			pre[i]=pre[i-1]+(s[i]=='+'?1:-1)*((i&1)?1:-1);
    			if((s[i]=='+' and (i&1)) or (s[i]=='-' and !(i&1)))
    				g[0][pre[i]+maxn].push_back(i);
    			else g[1][pre[i]+maxn].push_back(i);
    		}
    		while(q--) {
    			int x,y;
    			x=read(9),y=read(9);
    			if(pre[y]-pre[x-1]==0)
    				puts("0");
    			else if((y-x)&1) {
    				puts("2");
    				print(x,' ');
    				calc(x+1,y);
    			}
    			else {
    				puts("1");
    				calc(x,y);
    			}
    		}
    		for(int i=1;i<=n;++i)
    			if((s[i]=='+' and (i&1)) or (s[i]=='-' and !(i&1)))
    				g[0][pre[i]+maxn].clear();
    			else g[1][pre[i]+maxn].clear();
    	}
    	return 0;
    }
    
  • 相关阅读:
    bits,Bytes,KB,MB,GB和TB之间的换算关系
    idea快捷键
    拦截器Interceptor和过滤器Filter的区别
    JSTL标签
    EL 表达式
    El 表达式和 Jstl 标签库
    JavaWeb servlet,乱码的原因和解决
    java类从加载、连接到初始化过程
    js中获取监听键盘事件
    ASP.NET Core Web 支付功能接入 微信-扫码支付篇(转)
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15208222.html
Copyright © 2011-2022 走看看