• 【题解】 luogu p3674小清新人渣的本愿


    题目链接

    算法:bitset+莫队

    先把询问都离线下来,用莫队判断每个询问区间。并维护两个bitset (s_1,s_2),一个判断 (a_i)是否在当前区间内。若&a_i&在bitset1中位上的值为true,那(n-a_i)在bitset2中那一位上也为true。

    关于操作一,其实就是询问 是否有两个数(a,b)在区间内,满足(a+x=b)。那么我们只需要把(s1)左移x位并&上自己,看结果是否不为0就好了,因为若不为0,说明有一个数(a+x)(a)同时在区间内。

    关于操作二,考虑把它转换成操作一,若存在两个数(a_i,b_i),使(a_i+b_i=x),设(n-a_i)(o),那么(n-o+b_i=x),则(o-b_i=n-x),这样就转换成了操作一,把(s_2)左移(n-x)位然后再&上(s_1)看结果就好了

    操作三不好用bitset做,就直接暴力枚举约数暴搞就好了,说实话这个操作和这题有点格格不入。

    记得弄个桶判一下每个元素个数,这个题有重复元素。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <bitset>
    #define maxn 1000005
    
    int n,m,a[maxn],bar[maxn],len,ans[maxn],ton[maxn];
    std::bitset <maxn> s1,s2,k;
    struct question{
    	int l,r,opt,x,whi;
    }op[maxn];
    
    bool cmp(question q,question p) {
    	if (bar[q.l] == bar[p.l]) return q.r < p.r;
    	else return bar[q.l] < bar[p.l];
    }
    void mo() {
    	int ll = 1,rr = 0;
    	for (int i = 1;i <= m;i++) {
    		while (rr < op[i].r) {
    			rr++;
    			if ((++ton[a[rr]]) > 0)s1.set(a[rr]),s2.set(n - a[rr]);
    		}
    		while (ll > op[i].l) {
    			ll--;
    			if ((++ton[a[ll]]) > 0)s1.set(a[ll]),s2.set(n - a[ll]);
    		}
    		while (rr > op[i].r) {
    			if ((--ton[a[rr]]) <= 0)s1.set(a[rr],0),s2.set(n - a[rr],0);
    			rr--;
    		}
    		while (ll < op[i].l) {
    			if (!(--ton[a[ll]]))s1.set(a[ll],0),s2.set(n - a[ll],0);
    			ll++;
    		}
    		if (op[i].opt == 1) {
    			k = (s1 & (s1 << op[i].x));
    			if (k.any()) ans[op[i].whi] = 1;
    		}
    		else if (op[i].opt == 2) {
    			k = (s1 & (s2 >> (n - op[i].x)));
    			if (k.any()) ans[op[i].whi] = 1;
    		}
    		else {
    			for (int j = 1;j <= sqrt(op[i].x);j++) {
    				if (op[i].x % j == 0 && s1[j] && s1[op[i].x / j]) ans[op[i].whi] = 1;
    			}
    		}
    	}
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int i = 1;i <= n;i++) {
    		scanf("%d",&a[i]);
    	}
    	for (int i = 1;i <= m;i++) 
    		scanf("%d%d%d%d",&op[i].opt,&op[i].l,&op[i].r,&op[i].x),op[i].whi = i;
    	len = sqrt(n);
    	for (int i = 1;i <= n;i++) {
    		bar[i] = i / len + 1;
    	}
    	std::sort(op + 1,op + m + 1,cmp);
    	mo();
    	for (int i = 1;i <= m;i++) {
    		if (ans[i]) printf("hana
    ");
    		else printf("bi
    ");
    	}
    	return 0;
    }
    
    
    
  • 相关阅读:
    OSGI .Net 框架学习
    ArcEngine开发过程中的空间关系
    ITOCControl添加鼠标右键菜单
    IHookHelper的使用
    ITopologicalOperator接口调用
    GeoProcessor的使用方法
    ArcEngine内置工具条
    OSGI.NET插件方式开发你的应用
    C#在linux上运行实现
    Linux 下随机启动自己的应用 -请使用while(true) 不要Console.ReadKey()
  • 原文地址:https://www.cnblogs.com/Illusions/p/14023747.html
Copyright © 2020-2023  润新知