2019徐州網路賽I題

2021-09-26 23:13:59 字數 2065 閱讀 4891

已知數列p是1~n的排列,現在給定m組詢問,每組詢問給出左右端點l和r,求出[l,r]區間中有多少對滿足p[i]%p[j]=0 或 p[j]%p[i]=0,要求i首先維護乙個字首和sum,其中sum[i]維護的是[1,i]中滿足條件的對數。

那麼對於詢問[l,r],結果就是sum[r]-sum[l-1]。

但是這看上去有些問題,因為存在i在[1,l-1],j卻在[l,r]上的情況。

於是我們用乙個樹狀陣列來維護這種情況,在查詢完乙個左端點l後,將它所有的倍數(除了它自己)全都更新,每次查詢結果減去ask®-ask(l-1)。

舉個例子,樣例為

5 2

1 2 3 4 5

1 53 5

第一次查詢完成後,樹狀陣列會在[2,5]區間上都+1,表示這些是1的倍數。在去查[3,5]區間時,就會減去這些值。

**寫的有些醜陋,因為之前讀錯題了套了乙個莫隊的板子,多了乙個f結構體陣列,其實用不到。

#include

using

namespace std;

const

int maxn =

100005

;typedef

long

long ll;

template

<

class

t>

void

read

(t &x)

while

(s>=

'0'&&s<=

'9')

x *= f;

}struct node

bool

operator

<

(const node &b)

const};

int block;

struct node2

}f[maxn]

;int c[maxn]

,a[maxn]

,ans2[maxn]

,n,m,res,pos[maxn]

,sum[maxn]

,cnt[maxn]

,cnt[maxn]

,ans[maxn]

;vector<

int> e[maxn]

;vector q[maxn]

;int

lowbit

(int x)

void

update

(int x)

intask

(int x)

intmain()

for(

int i=

1;i<=n;i++)}

for(

int i=

1;i<=n;i++

)sort

(e[i]

.begin()

,e[i]

.end()

);for(

int i=

1;i<=n;i++

) sum[i]

= sum[i-1]

+ cnt[i]

;for

(int i=

1;i<=n;i++

)int temp =

upper_bound

(e[i]

.begin()

,e[i]

.end()

,i)- e[i]

.begin()

;for

(int j=temp;j.size()

;j++

)update

(e[i]

[j]);}

for(

int i=

1;i<=m;i++

)printf

("%d\n"

,ans[i]

-(f[i]

.r-f[i]

.l+1))

;// for(int i=1;i<=m;i++) cout << ans2[i] << ' ';

return0;

}

2019徐州網路賽 query

題目鏈結 題解,這個題目巧妙地按下標進行樹狀陣列處理,先預處理所有有倍數關係的和每個元素的位置i,然後把下標小的存到下標大 的陣列中,查詢也離線,然後從左到右,邊加入,邊求和。include include include using namespace std int n int sum 1000...

2019ICPC徐州網路賽

theme n個數編號為1 n,兩種操作 1 x 將編號為x的數置為不可得,2 x 詢問x位置及其後第乙個可得數的編號。1 n,x 1e9,1 q 1e6 solution 首先想到用線段樹維護。初始時線段樹每個l r位置的值為l,1 x操作對應將x位置值置為inf,2 x 操作相當於查詢區間 x,...

2018徐州網路賽

a.hard to prepare dp 題目 題意 環形圈中,給每人乙個號碼,求使得相鄰數字反異或為正數的方案數。有題意可推出,每兩個數反異或要麼是0要麼是正數,所以也就是讓相鄰數字反異或後不能為0。又知道,與某個數反異或之後為0的只有唯一乙個數,因此可推出第1個人到第n個人分別可選的數的個人為 ...