Icpc訓練賽 國慶大禮包

2021-08-09 02:24:35 字數 3692 閱讀 2586

[problem]

有a、b兩個集合以及n個人,每個人所屬乙個集合。維護兩種操作:d x y 代表x和y屬於不同聚合;a x y 判斷xy是否屬於乙個集合

[solution]

用i代表第i個人屬於a集合, i + n代表第i個人屬於b集合,即每個數字表示一種限制條件;數字在同乙個集合表示對應的條件必須同時滿足;

對於d(x,y):union(x, y + n), union(x + n, y)

對於a(x,y) : 判斷(x, y)與(x+ n ,y+ n) 的所屬集合

[code]

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

int f[210000];

int n, m;

int find(int x)

void unio(int x, int y)

bool cal(int x, int y)

int main()

else }}

return

0;}

[problem]

給定一段環形序列,求解最大子串行連續和,確保不是原全部序列

[solution]

對於樸素的最大子串行連續和,可以用動態規劃來實現,即dp[i] = max(dp[i - 1], dp[i - 1] + a[i]) 那可不可以把環形的序列轉化到線性上來呢?可以把原序列複製一遍,放到原序列後面,這樣對於環形的每種情況,都可以在新序列中體現出來,但注意到,新序列的一些連續子串行不一定合法(長度可能超過n),成功gg

我們考慮a[1]~a[n],如果我們單獨對這個序列求解最大連續子串行和,會少考慮環形序列中跨越a[1]和a[n]的情況,在這種情況下,原序列和是固定的,選取的連續子串行和最大,但是剩餘的連續和最小,因此我們只需要求解出a[1]~a[n]中最大連續子串行和、最小連續子串行和即可。

對於修改操作,通過線段樹單點修改即可。

#include

#include

#include

#include

#include

#include

using namespace std

;const int n = 110000

;typedef long long ll;

#define lson x << 1, l, mid

#define rson x << 1 | 1, mid + 1, r

#define lx x << 1

#define rx x << 1 | 1

int ql, qr, qa;

int n, m;

int a[n];

struct node tree[n << 2];

void pushup(int x)

void build(int x, int l, int r)

build(lson);

build(rson);

pushup(x);

}void update(int x, int l, int r)

if (ql <= mid) update(lson); else update(rson);

pushup(x);

}int main()

return 0

;}

[problem]

n個spaceship,每個有速度和位置,最後詢問碰撞次數,並輸出前10000次碰撞

[solution]

碰撞次數就是逆序對的次數,用樹狀陣列來搞

顯然,每次碰撞都是相鄰的先發生碰撞,因此我們用線段樹來維護每個spaceship發生碰撞的時間,每次取出所用時間最短的碰撞,然後更新這兩個點的time,注意同時也可能會影響周圍的時間。

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

#define lson x << 1, l, mid

#define rson x << 1 | 1, mid + 1, r

#define lx x << 1

#define rx x << 1 | 1

#define inf 1e10

#define mo 1000000

const

int n = 300000;

int n ,m;

int ql;

struct node a[n];

struct dat tree[n << 2];

int c[n];

int lowbit(int x)

void add(int x, int val)

}int sum(int x)

return ret;

}bool cmp(dat x, dat y)

return x.minn < y.minn;

}void pushup(int x)

void build(int x, int l, int r)

int mid = (l + r) >> 1;

build(lson);

build(rson);

pushup(x);

}void update(int x, int l, int r)

int mid = (l + r) >> 1;

if (ql <= mid) update(lson);

else update(rson);

pushup(x);

}int calc()

return ans;

}int main()

for(int i = 1; i < n; i++)

a[n].val = inf;

build(1, 1, n);

printf("%d\n", calc());

for(int i = 1; i <= 10000; i++)

node pre = a[num + 1];

a[num + 1] = a[num];

a[num + 1].val = inf;

if (num + 2

<= n && a[num + 1].v > a[num + 2].v) a[num + 1].val = abs((a[num + 2].x - a[num + 1].x)) / (a[num + 1].v - a[num + 2].v);

ql = num + 1;

update(1, 1, n);

a[num] = pre;

a[num].val = inf;

ql = num;

update(1, 1, n);

}return

0;}

訓練 9 13 訓練賽

a.hdu 6230 乙個合法的子串 s 3n 2 滿足條件即1 2n 1 為以n為回文中心的回文串,n 3n 2為以2n 1為中心的回文串。故我們可以通過尋找回文中心對,來判斷相應合法子串的個數。利用manacher求出每個位置的最長回文半徑,則若i,j滿足條件 i j 則應有 p i geqsl...

訓練賽 詠歎

安師大附中訓練題目 給定乙個1到n的排列a,對其進行氣泡排序 counter 0 while a不是公升序的 counter counter 1 for i 1 to n 1 if a i a i 1 then swap a i a i 1 endifend forend while那麼經過幾輪排序...

訓練賽 浣熊

從前有乙隻可愛的小浣熊居住在美麗的森林裡。他聽說小鸚鵡要旅行到另乙隻鸚鵡家做客,也想邀請朋友們來自己家。為此,小浣熊想建一棟新房子。他找到了一塊比較大的平地,不過這塊地上還是有一些地方不能建屋。不妨把這塊空地看作是由n行m列等大小的正方形格仔組成。現在,小熊已經把不能建房子的地方都標記了出來,他想找...