/*************************************************************************
> File Name: algo_1.cpp
> Author: gwq
> Mail: [email protected]
> Created Time: 2014年11月08日 星期六 12時58分31秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
#define N 1010
int num[N], tmp[N];
int findk(int k, int l, int r)
{
int key = tmp[l];
int i = l;
int j = r;
//當i==j的時候就找到了key在數組中的下標,就是i
while (i < j) {
while (i < j && tmp[j] >= key) {
--j;
}
tmp[i] = tmp[j];
while (i < j && tmp[i] <= key) {
++i;
}
tmp[j] = tmp[i];
}
tmp[i] = key;
if (i == k) {
return tmp[k];
} else if (i < k) {
return findk(k, i + 1, r);
} else {
return findk(k, l, r - 1);
}
}
int main(int argc, char *argv[])
{
int n, m, l, r, k;
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; ++i) {
scanf("%d", &num[i]);
}
scanf("%d", &m);
for (int i = 0; i < m; ++i) {
scanf("%d%d%d", &l, &r, &k);
int cnt = 0;
for (int j = l; j <= r; ++j) {
tmp[cnt++] = num[j];
}
//這種先排序,再取第k大的複雜度是mnlogn
//這裏給的數據量小,可以忍受,還有一種方法
//是利用快排的思想,可以把複雜度降爲mn,單次
//查詢第k大的複雜度是logn。
//從小到大排序
//sort(tmp, tmp + cnt);
//第k大的下標就是cnt-k
//printf("%d\n", tmp[cnt - k]);
//需要尋找下標爲cnt-k的數
printf("%d\n", findk(cnt - k, 0, cnt - 1));
}
}
return 0;
}
/*
算法訓練 區間k大數查詢
時間限制:1.0s 內存限制:256.0MB
問題描述
給定一個序列,每次詢問序列中第l個數到第r個數中第K大的數是哪個。
輸入格式
第一行包含一個數n,表示序列長度。
第二行包含n個正整數,表示給定的序列。
第三個包含一個正整數m,表示詢問個數。
接下來m行,每行三個數l,r,K,表示詢問序列從左往右第l個數到第r個數中,從大往小第K大的數是哪個。序列元素從1開始標號。
輸出格式
總共輸出m行,每行一個數,表示詢問的答案。
樣例輸入
5
1 2 3 4 5
2
1 5 2
2 3 2
樣例輸出
4
2
數據規模與約定
對於30%的數據,n,m<=100;
對於100%的數據,n,m<=1000;
保證k<=(r-l+1),序列中的數<=10^6。
*/
/*************************************************************************
> File Name: algo_2.cpp
> Author: gwq
> Mail: [email protected]
> Created Time: 2014年11月08日 星期六 13時26分29秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
/*
* 這個在藍橋杯的訓練網站上只得到60分
* 不知道是什麼原因。
*/
int main(int argc, char *argv[])
{
ll n;
while (cin >> n) {
ll ans;
if (n <= 2) {
//處理好特殊情況
ans = n;
} else if (n % 2 == 1) {
//當n爲奇數時,n,n-1,n-2這三個數一定互質
//相鄰的兩個整數一定是互質的
ans = n * (n - 1) * (n - 2);
} else if (n % 3 != 0) {
//當n爲偶數時,並且n不能被3整除,那麼n,n-1,n-3
//這3個數一定互質,並且不能找到更大的數了
ans = n * (n - 1) * (n - 3);
} else {
//當n爲偶數,並且能被3整除時,根據上邊的說法,
//這個3個數互質,並且也不能找到更大的數了
ans = (n - 1) * (n - 2) * (n - 3);
}
cout << ans << endl;
}
return 0;
}
/*
算法訓練 最大最小公倍數
時間限制:1.0s 內存限制:256.0MB
問題描述
已知一個正整數N,問從1~N中任選出三個數,他們的最小公倍數最大可以爲多少。
輸入格式
輸入一個正整數N。
輸出格式
輸出一個整數,表示你找到的最小公倍數。
樣例輸入
9
樣例輸出
504
數據規模與約定
1 <= N <= 10^6。
*/
/*************************************************************************
> File Name: algo_3.cpp
> Author: gwq
> Mail: [email protected]
> Created Time: 2014年11月08日 星期六 20時32分00秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
#define N 110
#define MOD (1000000007)
//數位dp,dp[i][j]表示i位數最高位是j的符合題意的數的個數
int dp[N][N];
int main(int argc, char *argv[])
{
int K, L;
while (scanf("%d%d", &K, &L) != EOF) {
clr(dp, 0);
for (int i = 0; i < K; ++i) {
dp[1][i] = 1;
}
for (int i = 2; i <= L; ++i) {
for (int j = 0; j < K; ++j) {
for (int k = 0; k < K; ++k) {
if (k != j - 1 && k != j + 1) {
dp[i][j] = (dp[i][j] + dp[i - 1][k]) % MOD;
}
}
}
}
int ans = 0;
for (int i = 1; i < K; ++i) {
ans = (ans + dp[L][i]) % MOD;
}
printf("%d\n", ans);
}
return 0;
}
/*
算法訓練 K好數
時間限制:1.0s 內存限制:256.0MB
問題描述
如果一個自然數N的K進製表示中任意的相鄰的兩位都不是相鄰的數字,
那麼我們就說這個數是K好數。求L位K進制數中K好數的數目。
例如K = 4,L = 2的時候,所有K好數爲11、13、20、22、30、31、33 共7個。
由於這個數目很大,請你輸出它對1000000007取模後的值。
輸入格式
輸入包含兩個正整數,K和L。
輸出格式
輸出一個整數,表示答案對1000000007取模後的值。
樣例輸入
4 2
樣例輸出
7
數據規模與約定
對於30%的數據,KL <= 10^6;
對於50%的數據,K <= 16, L <= 10;
對於100%的數據,1 <= K,L <= 100。
*/
/*************************************************************************
> File Name: algo_4.cpp
> Author: gwq
> Mail: [email protected]
> Created Time: 2015年03月19日 星期四 14時04分19秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-5;
#define N 100010
int dp[N][2], n;
vector<int> edge[N];
void dfs(int u, int f)
{
for (int i = 0; i < sz(edge[u]); ++i) {
int v = edge[u][i];
if (f != v) {
dfs(v, u);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
}
}
int main(int argc, char *argv[])
{
while (scanf("%d", &n) != EOF) {
clr(dp, 0);
for (int i = 1; i <= n; ++i) {
scanf("%d", &dp[i][1]);
}
for (int i = 1; i < n; ++i) {
int u, v;
scanf("%d%d", &u, &v);
edge[u].pb(v);
edge[v].pb(u);
}
dfs(1, -1);
printf("%d\n", dp[1][0]);
}
return 0;
}
/*
問題描述
有一棵 n 個節點的樹,樹上每個節點都有一個正整數權值。如果一個點被選擇了,
那麼在樹上和它相鄰的點都不能被選擇。求選出的點的權值和最大是多少?
輸入格式
第一行包含一個整數 n 。
接下來的一行包含 n 個正整數,第 i 個正整數代表點 i 的權值。
接下來一共 n-1 行,每行描述樹上的一條邊。
輸出格式
輸出一個整數,代表選出的點的權值和的最大值。
樣例輸入
5
1 2 3 4 5
1 2
1 3
2 4
2 5
樣例輸出
12
樣例說明
選擇3、4、5號點,權值和爲 3+4+5 = 12 。
數據規模與約定
對於20%的數據, n <= 20。
對於50%的數據, n <= 1000。
對於100%的數據, n <= 100000。
權值均爲不超過1000的正整數。
*/
/*************************************************************************
> File Name: algo_5.cpp
> Author: gwq
> Mail: [email protected]
> Created Time: 2015年03月19日 星期四 14時58分31秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-5;
#define N 20010
struct Node {
int v, d;
};
int n, m, d[N], vis[N];
vector<Node> edge[N];
// 普通的dijkstra運行超時,得使用堆優化的dijkstra
void dijkstra(void)
{
clr(d, 0);
clr(vis, 0);
int s = 1;
for (int i = 1; i <= n; ++i) {
if (i == s) {
d[i] = 0;
} else {
d[i] = INF;
}
}
for (int i = 1; i <= n; ++i) {
int x;
int dis = INF;
for (int j = 1; j <= n; ++j) {
if (vis[j] == 0 && dis > d[j]) {
x = j;
dis = d[j];
}
}
vis[x] = 1;
// vector的下標是從0開始的
for (int j = 0; j < sz(edge[x]); ++j) {
int v = edge[x][j].v;
d[v] = min(d[v], d[x] + edge[x][j].d);
}
}
}
int main(int argc, char *argv[])
{
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 0; i < m; ++i) {
int u, v, l;
scanf("%d%d%d", &u, &v, &l);
Node x;
x.v = v;
x.d = l;
edge[u].pb(x);
}
dijkstra();
for (int i = 2; i <= n; ++i) {
printf("%d\n", d[i]);
}
}
return 0;
}
/*
問題描述
給定一個n個頂點,m條邊的有向圖(其中某些邊權可能爲負,但保證沒有負環)。
請你計算從1號點到其他點的最短路(頂點從1到n編號)。
輸入格式
第一行兩個整數n, m。
接下來的m行,每行有三個整數u, v, l,表示u到v有一條長度爲l的邊。
輸出格式
共n-1行,第i行表示1號點到i+1號點的最短路。
樣例輸入
3 3
1 2 -1
2 3 -1
3 1 2
樣例輸出
-1
-2
數據規模與約定
對於10%的數據,n = 2,m = 2。
對於30%的數據,n <= 5,m <= 10。
對於100%的數據,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,
保證從任意頂點都能到達其他所有頂點。
*/
/*************************************************************************
> File Name: algo_5_heap.cpp
> Author: gwq
> Mail: [email protected]
> Created Time: 2015年03月19日 星期四 14時58分31秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-5;
#define N 20010
struct Node {
int v, d;
};
int n, m, d[N], vis[N];
vector<Node> edge[N];
void dijkstra(void)
{
clr(vis, 0);
for (int i = 1; i <= n; ++i) {
if (i == 1) {
d[i] = 0;
} else {
d[i] = INF;
}
}
priority_queue<pii, vector<pii>, greater<pii> > pq;
pq.push(make_pair(0, 1));
while (!pq.empty()) {
pii x = pq.top();
pq.pop();
int u = x.second;
if (vis[u]) {
continue;
}
vis[u] = 1;
for (int i = 0; i < sz(edge[u]); ++i) {
int v = edge[u][i].v;
if (d[v] > d[u] + edge[u][i].d) {
d[v] = d[u] + edge[u][i].d;
pq.push(make_pair(d[v], v));
}
}
}
}
int main(int argc, char *argv[])
{
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 0; i < m; ++i) {
int u, v, l;
scanf("%d%d%d", &u, &v, &l);
Node x;
x.v = v;
x.d = l;
edge[u].pb(x);
}
dijkstra();
for (int i = 2; i <= n; ++i) {
printf("%d\n", d[i]);
}
}
return 0;
}
/*
問題描述
給定一個n個頂點,m條邊的有向圖(其中某些邊權可能爲負,但保證沒有負環)。
請你計算從1號點到其他點的最短路(頂點從1到n編號)。
輸入格式
第一行兩個整數n, m。
接下來的m行,每行有三個整數u, v, l,表示u到v有一條長度爲l的邊。
輸出格式
共n-1行,第i行表示1號點到i+1號點的最短路。
樣例輸入
3 3
1 2 -1
2 3 -1
3 1 2
樣例輸出
-1
-2
數據規模與約定
對於10%的數據,n = 2,m = 2。
對於30%的數據,n <= 5,m <= 10。
對於100%的數據,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,
保證從任意頂點都能到達其他所有頂點。
*/
/*************************************************************************
> File Name: algo_6.cpp
> Author: gwq
> Mail: [email protected]
> Created Time: 2015年03月20日 星期五 16時29分52秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
const double esp = 1e-5;
#define N 100010
int c[N], n, p, m[N];
struct Node {
int u, v, w;
void input(void)
{
scanf("%d%d%d", &u, &v, &w);
// 以這個爲新的權值。再加上住處的時間就行了
w = 2 * w + c[u] + c[v];
}
}node[N];
bool cmp(Node u, Node v)
{
return u.w < v.w;
}
int find(int x)
{
return ((m[x] == x) ? x : (m[x] = find(m[x])));
}
int main(int argc, char *argv[])
{
while (scanf("%d%d", &n, &p) != EOF) {
int minn = INF;
for (int i = 1; i <= n; ++i) {
scanf("%d", &c[i]);
minn = min(minn, c[i]);
}
for (int i = 0; i < p; ++i) {
node[i].input();
}
sort(node, node + p, cmp);
for (int i = 1; i <= n; ++i) {
m[i] = i;
}
int ans = 0;
for (int i = 0; i < p; ++i) {
int x = find(node[i].u);
int y = find(node[i].v);
if (x != y) {
m[x] = y;
ans += node[i].w;
}
}
printf("%d\n", ans + minn);
}
return 0;
}
/*
問題描述
Farmer John變得非常懶,他不想再繼續維護供奶牛之間供通行的道路。道路被用來連
接N個牧場,牧場被連續地編號爲1到N。每一個牧場都是一個奶牛的家。FJ計劃除去P條
道路中儘可能多的道路,但是還要保持牧場之間 的連通性。你首先要決定那些道路是
需要保留的N-1條道路。第j條雙向道路連接了牧場Sj和Ej(1 <= Sj <= N; 1 <= Ej <= N;
Sj != Ej),而且走完它需要Lj的時間。沒有兩個牧場是被一條以上的道路所連接。奶牛
們非常傷心,因爲她們的交通系統被削減了。你需要到每一個奶牛的住處去安慰她們。
每次你到達第i個牧場的時候(即使你已經到過),你必須花去Ci的時間和奶牛交談。
你每個晚上都會在同一個牧場(這是供你選擇的)過夜,直到奶牛們都從悲傷中緩過神來。
在早上 起來和晚上回去睡覺的時候,你都需要和在你睡覺的牧場的奶牛交談一次。
這樣你才能完成你的 交談任務。假設Farmer John採納了你的建議,請計算出使所有
奶牛都被安慰的最少時間。
輸入格式
第1行包含兩個整數N和P。
接下來N行,每行包含一個整數Ci。
接下來P行,每行包含三個整數Sj, Ej和Lj。
輸出格式
輸出一個整數, 所需要的總時間(包含和在你所在的牧場的奶牛的兩次談話時間)。
樣例輸入
5 7
10
10
20
6
30
1 2 5
2 3 5
2 4 12
3 4 17
2 5 15
3 5 6
樣例輸出
176
數據規模與約定
5 <= N <= 10000,N-1 <= P <= 100000,0 <= Lj <= 1000,1 <= Ci <= 1,000。
*/