luogu3674 小清新人渣的本願

2022-05-05 12:27:10 字數 2925 閱讀 9723

目錄本題解法

給定長度為\(n\)數列\(a\) ,\(m\)組查詢,問\([l,r]\)內是否有兩個數之和/差/積為\(x\),

\(n,m\le 10^5,max\\le10^5​\)

傳送門我們先來介紹一下 bitset

如果您熟悉bitset請跳至下一章

bitset十分神奇,你可以把它看作乙個支援整體操作的bool陣列。

bitset的原理是基於類似把long long拆成64個二進位制位,從而使它的整體時間和空間降至\(o(\frac)\)

其中,\(\omega=64\) (在64位機中)。

建構函式

bitset<10> bs("0000000000");//0000000000

//這裡10表示這個bitset共十位,前面不夠補0.

//這裡字串既可以是乙個string,也可以是char

bitset<10> bs1(128);//0010000000

bitset<2> bs2(128);//00

//這裡128=(0010000000),取末兩位,string/char構造時同理。

運算
bs=64;//0001000000

bs|=11;//0001001011

bs1&=2;//0000000010

bs^=64;//0000001011

bs<<=1;//0000010110

bs>>=2;//0000000101

bs2=~bs2;//11(按位取反)

//bitset支援&,|,^,<<,>>,~和數字/bitset進行運算(也支援比較相等關係(==,!=))

函式
cout《其中除 取某一位(如bs[2])複雜度為\(o(1)\) ,其餘均為\(o(\frac)\)

// flip()取反整個bitset或其中某位。

bitset<10> bs3("1110101111");

bs3.flip(); //0001010000

//相當於bs3=~bs3;

bs3.flip(1);//0001010010

//bs3[1]=!bs3[1];

// set()將整個bitset或其中某位設為1。

bs3.set(); //1111111111

bs3.set(3,0);//1111110111

bs3.set(3); //1111111111

//reset()與set()類似

bs3.reset(3) //1111110111

bs3.reset() //0000000000

其中除對某一位進行操作外,其餘複雜度為\(o(n)\)

莫隊+bitset

我們先來考慮操作1

即找\[a-b=x\]即

\[a=b+x

\]我們用莫隊 維護乙個bitset(bs), bs的每一位維護乙個數的出現情況

在查詢時查詢(bs&(bs《操作2:

再來一次

\[a+b=x

\\a=-b+x

\]bitset不可以維護負數,似乎很不可做,怎麼辦?

將維護負數的bitset(bs1)左移n位(n即為出現數的最大值)!

這樣\[bs[i]=bs1[n-i]

\]查詢時將bs1右移\(n-x\)位,即原負數bitset左移x位

即(bs&(bs1>>(n-x))).any()

操作3:

跳出思維定勢!

x很小,直接列舉因數即可

複雜度即為\(o(m\sqrt m+m*\frac)\)

應該能過

/*

author:pmt

program:luogu p3674

*/#include#define local

#define mp make_pair

#define pb push_back

#define y0 _pmty0

#define x0 _pmtx0

#define y1 _pmty1

#define x1 _pmtx1

#define next _pmtnxt

#define pipe _pmtppie

#define lson(id) (id<<1)

#define rson(id) (id<<1|1)

using namespace std;

typedef long long ll ;

typedef unsigned long long ull ;

typedef vectorvi;

typedef vectorvll;

typedef pairpii;

typedef vectorvii;

inline int read()

while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();

return s*w;

}void write(int x)

const int inf=0x3f3f3f3f, maxn=100007,n=100007, mod=1e9+7;

const ll linf=0x3f3f3f3f3f3f3f3fll;

const ll p=19260817;

int n,m;

bitsetbs1,bs2;

int a[maxn];

int cnt[maxn];

struct nodeq[maxn];

int b;

bool ans[maxn];

bool cmp(const node &a ,const node &b)}}

}for(int i=1;i<=m;i++)

return 0;

}

Luogu3674小清新人渣的本願

給你乙個序列a,長度為n,有m次操作,每次詢問乙個區間 bitset 的原理是將一大堆值為 0 1 的數壓成乙個數。通過 i x 等操作,我們可以快速訪問 i 陣列右移 x 位後的狀態 即只剩右數 n x 個值。bitset 陣列可以當作乙個數來看待並進行 等操作 詳見高斯消元總結 還有一些 stl...

luogu P3674 小清新人渣的本願

題目背景 本題時限3s,空間128mb 我感覺我要掛省選 人渣的本願是乙個有趣的番 可愛的花火喜歡從小和她談 笑 風 生的歐 尼 醬鳴海,歐尼醬特別想當老師,然後劇本安排當了花火的班主任。然而有個叫做皆川茜的奇怪的人搶走了歐尼醬!花火就很失落呀,然後看到乙個叫做麥的人也很失落,原來麥喜歡茜老師。花火...

題解 luogu p3674小清新人渣的本願

題目鏈結 演算法 bitset 莫隊 先把詢問都離線下來,用莫隊判斷每個詢問區間。並維護兩個bitset s 1,s 2 乙個判斷 a i 是否在當前區間內。若 a i 在bitset1中位上的值為true,那 n a i 在bitset2中那一位上也為true。關於操作一,其實就是詢問 是否有兩個...