BZOJ4810 [Ynoi2017]由乃的玉米田


本文版權歸ljh2000和博客園共有,歡迎轉載,但須保留此聲明,並給出原文鏈接,謝謝合作。

 

 

 

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
轉載請注明出處,侵權必究,保留最終解釋權!

 

題目鏈接:BZOJ4810

正解:$bitset$+莫隊算法

解題報告:

  考慮直接上$bitset$會$MLE$,我們用莫隊來優化空間,不用每個點都開一個。

  維護一個$cnt$數組,表示每種值的出現次數,那么我可以用$bitset$維護每種權值是否出現過。

  考慮乘法操作的話,直接利用$cnt$數組,每次暴枚所有因子,$check$一下就好了;

  對於減法操作,相當於是查詢是否存在$i$,$j$滿足$a[i]-a[j]=x$的形式,那么把$bitset$右移$x$位與原來的&一下看新的二進制數是否為$0$(用$bitset$自帶的$count$就好了);

  加法類似,不過需要維護的是$a[i]+a[j]=x$的形式,那么我用$c$($c$是所有數中的最大值)去減$a[j]$,即變成$a[i]=(c-a[j])+x-c$的形式,另外維護一個$bitset$,右移$(c-x)$位查詢就好了。所以總復雜度就是$O(n\sqrt{n}+\frac{n^2}{32})$。

 

//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦關終屬楚;苦心人,天不負,卧薪嘗膽,三千越甲可吞吳。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <bitset>
#include <queue>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long LL;
const int MAXN = 200011;
int n,m,ans[MAXN],block,a[MAXN],b[MAXN],c,cnt[MAXN<<2];
bitset<100011>f,g,h;

struct ask{ int l,r,bel,id,x,type; }q[MAXN];
inline bool cmp(ask q,ask qq){ if(q.bel==qq.bel) return q.r<qq.r; return q.bel<qq.bel; }

inline int getint(){
    int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
    if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
}

inline void add(int x){
	cnt[a[x]]++;
	if(cnt[a[x]]==1) {
		f[a[x]]=1;
		g[b[x]]=1;
	}
}

inline void del(int x){
	cnt[a[x]]--;
	if(cnt[a[x]]==0) {
		f[a[x]]=0;
		g[b[x]]=0;
	}
}

inline bool query(ask tmp){
	int now;
	if(tmp.type==3) {//a[i]*a[j]=x
		now=sqrt(tmp.x+1);
		for(int i=1;i<=now;i++) {
			if(tmp.x%i==0) {
				if(cnt[i]>0 && cnt[tmp.x/i]>0) 
					return true;
			}
		}
	}
	else if(tmp.type==2) {//a[i]+a[j]=x
		h=g;
		h>>=(c-tmp.x);
		h&=f;
		if(h.count()) return true;
	}
	else {//a[i]-a[j]=x
		h=f;
		h>>=tmp.x;
		h&=f;
		if(h.count()) return true;
	}
	return false;
}

inline void work(){
	n=getint(); m=getint();block=2*sqrt(m); 
	c=100002; for(int i=1;i<=n;i++) a[i]=getint(),b[i]=c-a[i];
	for(int i=1;i<=m;i++) { q[i].type=getint(); q[i].l=getint(); q[i].r=getint(); q[i].x=getint(); q[i].id=i; q[i].bel=(q[i].l-1)/block+1; }
	sort(q+1,q+m+1,cmp); int l=q[1].l,r=q[1].r;
	for(int i=l;i<=r;i++) add(i)/*!!!*/;

	ans[q[1].id]=query(q[1]);
	for(int i=2;i<=m;i++) {
		while(r<q[i].r) r++,add(r);
		while(l>q[i].l) l--,add(l);
		while(r>q[i].r) del(r),r--;
		while(l<q[i].l) del(l),l++;
		ans[q[i].id]=query(q[i]);
	}
	for(int i=1;i<=m;i++) 
		if(ans[i]) puts("yuno");
		else puts("yumi");
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("4810.in","r",stdin);
	freopen("4810.out","w",stdout);
#endif
    work();
    return 0;
}
//有志者,事竟成,破釜沉舟,百二秦關終屬楚;苦心人,天不負,卧薪嘗膽,三千越甲可吞吳。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM