[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列等大小的正方形格仔組成。現在,小熊已經把不能建房子的地方都標記了出來,他想找...