• 思维
  • 贪心
    • 可反悔贪心
    • 模拟退火
  • 并查集
  • dp
  • 分治法
    • 最近点对
  • dfs
  • 组合数学——隔板法
  • 离散化 + 树状数组

思维

题:http://lx.lanqiao.cn/problem.page?gpid=T2908
题意:给定序列(a1,a2,……an),进行 m 次操作,p = 0,a1 ~ aq 降序排序,p = 1,aq ~ an 升序排序。
思路:如果是连续相同的操作,则取最大区间,可得两个操作是间或的,需要翻转的区间越来越小。根据操作去把数放好。

#include <iostream>#define x first
#define y secondusing namespace std;typedef pair<int, int> PII;const int N = 1e5 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 int n, m;
PII stk[N];
int ans[N];signed main()
{scanf("%d%d", &n, &m);int top = 0;while (m--){int p, q;scanf("%d%d", &p, &q);if (!p){while (top && stk[top].x == 0)q = max(q, stk[top--].y);while (top >= 2 && stk[top - 1].y <= q)top -= 2;stk[++top] = {0, q};}elseif (top){while (top && stk[top].x == 1)q = min(q, stk[top--].y);while (top >= 2 && stk[top - 1].y >= q)top -= 2;stk[++top] = {1, q};}}int k = n, l = 1, r = n;for (int i = 1; i <= top; ++i){if (stk[i].x == 0)while (r > stk[i].y && l <= r)ans[r--] = k--;elsewhile (l < stk[i].y && l <= r)ans[l++] = k--;if (l > r)break;}if (top % 2)while (l <= r)ans[l++] = k--;elsewhile (l <= r)ans[r--] = k--;for (int i = 1; i <= n; ++i)printf("%d ", ans[i]);return 0;
}

贪心

可反悔贪心

题:https://www.luogu.com.cn/problem/P1484

采用双向链表实现。

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
//#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
//#include <random>
#include <map>
//#include <unordered_map>    #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long
#define endl '\n' #define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<LL, int> PLI;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 5e5+ 5, MOD = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2
const double pi = 3.141592653589;double func(double x, double y)   //  评估函数
{return 6 * pow(x, 7.0) + 8 * pow(x, 6.0) + 7 * pow(x, 3.0) + 5 * pow(x, 2.0) - y * x;
}LL gcd(LL a, LL b)
{return b == 0 ? a : gcd(b, a % b);
}LL lcm(LL a, LL b)
{return a / gcd(a, b) * b;
}LL exgcd(LL a, LL b, LL &x, LL &y)
{if (!b){x = 1, y = 0;return a;}LL d = exgcd(b, a % b, y, x);y -= (a / b) * x;return d;
}LL wow[N];
int pre[N], nex[N];
bool v[N];
priority_queue<PLI> q;inline void del(int u)
{nex[pre[u]] = nex[u];pre[nex[u]] = pre[u];
}signed main()
{IOS;int n, m;cin >> n >> m;for (int i = 1; i <= n; ++i){cin >> wow[i];q.push({wow[i], i});pre[i] = i - 1;nex[i] = i + 1;}LL ans = 0, res = 0;while (m--){auto t = q.top();q.pop();while (v[t.second]){t = q.top();q.pop();}int u = t.second;v[nex[u]] = v[pre[u]] = true;ans += wow[u];if (res >= ans)break;elseres = ans;wow[u] = wow[nex[u]] + wow[pre[u]] - wow[u];del(nex[u]);del(pre[u]);q.push({wow[u], u});}cout << res << endl;return 0;
}

题:https://ac.nowcoder.com/acm/contest/32942/A

模拟退火

题:https://vjudge.net/contest/488791#problem/H
题意: F(x) = 6 * x^7 + 8 * x^6 + 7 * x^3 + 5 * x^2 - y * x (0 <= x <=100)。给出y的值,求F(x)的最小值。

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <random>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define int long long
#define endl '\n' #define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 2e6 + 5, MOD = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2
const double pi = 3.141592653589;const double T0 = 1e5, TK = 1e-8, d = 0.98;    //初始温度为高温,设置成一个大数;终止温度为低温,设置为一个接近于0的数;d是一个小于1但是非常接近于1的数double func(double x, double y)  //  评估函数
{return 6 * pow(x, 7.0) + 8 * pow(x, 6.0) + 7 * pow(x, 3.0) + 5 * pow(x, 2.0) - y * x;
}double simulateAnneal(double y)
{double T = T0, x = 50.0; //初始值double now = func(x, y);  //当前状态double nxt;   //新状态double ans = now; //最优解int f[2] = {-1, 1};while (T > TK){double newx = x + f[rand() % 2] * T;   //按概率改变x,温度越低概率越小if (newx >= 0 && newx <= 100){nxt = func(newx, y); //新状态ans = min(ans, nxt);  //在退火过程中维护遇到的所有解的最优值double dE = now - nxt; //能量差if (dE >= 0)   //新状态更优就接受{now = nxt;x = newx;}elseif (exp(dE / T) > rand())   //以一定概率接受{now = nxt;x = newx;}}T *= d;   //降温}return ans;
}signed main()
{IOS;int T;cin >> T;while (T--){double y;cin >> y;cout << fixed << setprecision(4) << simulateAnneal(y) << endl;}return 0;
}

并查集

题:https://vjudge.net/problem/POJ-1182
题意:A吃B,B吃C,C吃A。有两个操作,op=1,x和y是一个物种,op=2,x吃y,根据前面的真话去判断当前的话是真是假,输出假话数量。
思路:根据维护到祖宗结点距离的并查集,可以知道,有三层集合,0、1、2。1吃0,2吃1,3吃2,由于这是一个食物环,所以3跟0是一类的,可以根据距离%3判断是哪个集合的,然后判断当前的话是真是假。

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
//#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
//#include <random>
#include <map>
//#include <unordered_map>    #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long
#define endl '\n' #define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 5e4 + 5, MOD = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2
const double pi = 3.141592653589;double func(double x, double y)   //  评估函数
{return 6 * pow(x, 7.0) + 8 * pow(x, 6.0) + 7 * pow(x, 3.0) + 5 * pow(x, 2.0) - y * x;
}int n, m;
int p[N], d[N];int find(int x)
{if (p[x] != x){int t = find(p[x]);d[x] += d[p[x]];p[x] = t;}return p[x];
}signed main()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i)p[i] = i;int ans = 0;while (m--){int op, x, y;scanf("%d%d%d", &op, &x, &y);if (x > n || y > n)ans++;else{int px = find(x), py = find(y);if (op == 1){if (px == py && (d[x] - d[y]) % 3)ans++;elseif (px != py){p[px] = py;d[px] = d[y] - d[x];}}else{if (px == py && (d[x] - d[y] - 1) % 3)ans++;elseif (px != py){p[px] = py;d[px] = d[y] + 1 - d[x];}}}}printf("%d\n", ans);return 0;
}

dp

题:https://ac.nowcoder.com/acm/contest/32907/I

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
//#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
//#include <random>
#include <map>
//#include <unordered_map>    #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long
#define endl '\n' #define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 5e4 + 5, MOD = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2
const double pi = 3.141592653589;double func(double x, double y)   //  评估函数
{return 6 * pow(x, 7.0) + 8 * pow(x, 6.0) + 7 * pow(x, 3.0) + 5 * pow(x, 2.0) - y * x;
}LL gcd(LL a, LL b)
{return b == 0 ? a : gcd(b, a % b);
}LL lcm(LL a, LL b)
{return a / gcd(a, b) * b;
}LL exgcd(LL a, LL b, LL &x, LL &y)
{if (!b){x = 1, y = 0;return a;}LL d = exgcd(b, a % b, y, x);y -= (a / b) * x;return d;
}LL n, t, dp[105][5205][105], w[105], v[105];signed main()
{scanf("%lld%lld", &n, &t);for (int i = 1; i <= n; ++i)scanf("%lld%lld", &w[i], &v[i]);//这里用memset会超时for (int i = 0; i <= n; ++i)for (int j = 0; j <= 5200; ++j)for (int k = 0; k <= t; ++k)dp[i][j][k] = -INF;for (int k = 0; k <= t; ++k) //把n=1的情况单独更新出来{//选第一张卡if (k){dp[1][2600 + 2 * v[1]][k] = w[1];dp[1][2600 - 2 * v[1]][k] = w[1];}dp[1][2600 - v[1]][k] = w[1];dp[1][2600 + v[1]][k] = w[1];//不选第一张卡dp[1][2600][k] = 0;}for (int i = 2; i <= n; ++i)for (int j = 0; j <= 5200; ++j)for (int k = 0; k <= t; ++k){//不翻倍且不把第i张卡放入任何集合dp[i][j][k] = dp[i - 1][j][k];//翻倍且不把第i张卡放入任何集合的情况,不优,舍掉//dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1]);//把第i张卡翻倍放入A集合if (k >= 1 && j - 2 * v[i] >= 0)dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 2 * v[i]][k] + w[i]);//把第i张卡不翻倍放入A集合if (j - v[i] >= 0)dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - v[i]][k] + w[i]);//把第i张卡翻倍放入B集合if (k >= 1 && j + 2 * v[i] <= 5200)dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + 2 * v[i]][k - 1] + w[i]);//把第i张卡不翻倍放入B集合if (j + v[i] <= 5200)dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + v[i]][k] + w[i]);}printf("%lld\n", dp[n][2600][t]);return 0;
}

题:https://codeforces.com/contest/255/problem/C
题意:找到一个最长子序列p,q,p, q。(可以在给出的序列中任意删除元素)

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long#define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 4e3 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 int wow[N], dp[N][N];signed main()
{   int n, ans = 0;scanf("%d", &n);for (int i = 1; i <= n; ++i)   //子序列最后一个数是 i {scanf("%d", &wow[i]);for (int j = 0, id = 0; j < i; ++j)    //子序列倒数第二个数为 j{ dp[i][j] = dp[j][id] + 1;if (wow[i] == wow[j])id = j;  // id 记录前一个相等的数的位置ans = max(ans, dp[i][j]);}}printf("%d\n", ans);return 0;
}

题:https://ac.nowcoder.com/acm/contest/30789/D
题意:给出N个数,问是否能从中选出一些数字,使得其加和为3600的倍数

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long#define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 1e5 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 int wow;
bool dp[N], cnt[N];
int n;signed main()
{   int T;scanf("%d", &T);while (T--){memset(dp, false, sizeof dp);memset(cnt, false, sizeof cnt);int n;scanf("%d", &n);for (int i = 1; i <= n; ++i){scanf("%d", &wow);wow %= 3600;if (!dp[0]){for (int j = 0; j < 3600; ++j)if (dp[j] || !j)cnt[(wow + j) % 3600] = true;    //跟当前每个存在的数组成新值录入for (int j = 0; j < 3600; ++j)   //从cnt转存进dp{if (cnt[j])dp[j] = true;if (cnt[j])cnt[j] = false;}}}if (!dp[0])  //判断是否能组成模为0的printf("NO\n");elseprintf("YES\n");}return 0;
}

题:http://lx.lanqiao.cn/problem.page?gpid=T2900
题意:给定一个括号序列,要求尽可能少添加若干括号使之合法,求方案数。mod = 1e9 + 7。
思路:
左括号和右括号的插入是独立的,可以直接方案相乘起来。
插入左括号和插入右括号本质相同,将序列翻转后,每个字符也翻转即可。

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;typedef long long LL;const int N = 5010, MOD = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 int n;
char str[N];
LL f[N][N];LL calc()
{memset(f, 0, sizeof f);f[0][0] = 1;for (int i = 1; i <= n; ++i)if (str[i] == '(')for (int j = 1; j <= n; ++j)f[i][j] = f[i - 1][j - 1];else{f[i][0] = (f[i - 1][0] + f[i - 1][1]) % MOD;for (int j = 1; j <= n; ++j)f[i][j] = (f[i - 1][j + 1] + f[i][j - 1]) % MOD;}for (int i = 0; i <= n; ++i)if (f[n][i])return f[n][i];return -1;
}signed main()
{scanf("%s", str + 1);n = strlen(str + 1);LL l = calc();reverse(str + 1, str + n + 1);for (int i = 1; i <= n; ++i)if (str[i] == '(')str[i] = ')';elsestr[i] = '(';LL r = calc();printf("%lld\n", l * r % MOD);return 0;
}

题:https://ac.nowcoder.com/acm/contest/11224/D
题意:按顺序选一些字符串拼接起来,求字符串最大和,且两个拼接的字符串中前者的尾要与后者的头相同。
思路:

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long
#define endl '\n' #define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 2e5 + 10, MOD = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 int f[27];signed main()
{IOS;int T;cin >> T;while (T--){memset(f, 0, sizeof f);int n;cin >> n;for (int i = 1; i <= n; ++i){string s;cin >> s;f[s.back() - 'a'] = max(f[s.back() - 'a'], (int)s.size() + f[s[0] - 'a']);}int res = 0;for (int i = 0; i < 26; ++i)res = max(res, f[i]);cout << res << endl;}return 0;
}

题:https://vjudge.net/contest/488040#problem/F

分治法

最近点对

题:https://ac.nowcoder.com/acm/contest/31222/A
题意:
f(i, j) = ( i , j ) 2 (i, j)^2 (i,j)2 + g ( i , j ) 2 g(i, j)^2 g(i,j)2
g(i, j) = sum[j] - sum[i]
sum为前缀和数组
求最小f(i, j)
思路:转化为最近点对问题,下标作x,前缀和作y

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long#define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 1e5 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 struct Node
{LL id, sum;
}node[N];int tmp[N];inline bool cmp(int a, int b)
{return node[a].sum < node[b].sum;
}inline LL dis(int i, int j)
{return (node[i].id - node[j].id) * (node[i].id - node[j].id) + (node[i].sum - node[j].sum) * (node[i].sum - node[j].sum);
}LL closest(int l, int r)
{if (l == r)return 1e18;if (l + 1 == r)return dis(l, r);int mid = l + r >> 1;LL mm = min(closest(l, mid), closest(mid + 1, r));int tot = 0;for (int i = l; i <= r; ++i)if ((LL)(i - mid) * (i - mid) < mm)tmp[tot++] = i;sort(tmp, tmp + tot, cmp);for (int i = 0; i < tot; ++i)for (int j = i + 1; j < tot && (node[tmp[i]].sum - node[tmp[j]].sum) * (node[tmp[i]].sum - node[tmp[j]].sum) < mm; ++j)mm = min(mm, dis(tmp[i], tmp[j]));return mm;
}signed main()
{int n;scanf("%d", &n);node[0].sum = 0;for (int i = 1; i <= n; ++i){scanf("%lld", &node[i].sum);node[i].sum += node[i - 1].sum;node[i].id = i;}printf("%lld\n", closest(1, n));return 0;
}

dfs

题:https://atcoder.jp/contests/abc236/tasks/abc236_d
题意:共有2N个人,编号为1-2N,现要人们两两配对,若编号为i的人想与编号为j的人配对,i必须小于j,i与j配对后获得亲和力B。所有人配对完成后亲和力分别为B1,B2…BN,总乐趣为B1⊕B2⊕…⊕BN。求所有配对组合中总乐趣的最大值。

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long
#define endl '\n' #define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 3e5 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 int n, m, ans = 0;
vector <int> t;
int wow[20][20];
bool vis[20];void dfs(int p)
{if (t.size() == n){int tmp = t[0];for (int i = 1; i < t.size(); ++i)tmp ^= t[i];ans = max(ans, tmp);return ;}if (vis[p]){dfs(p + 1);return ;}for (int i = p + 1; i < 2 * n; ++i){if (!vis[i]){vis[p] = vis[i] = true;t.push_back(wow[p][i]);dfs(p + 1);t.pop_back();vis[p] = vis[i] = false;}}
}signed main()
{IOS;cin >> n;m = 2 * n;for (int i = 0, x; i < m - 1; ++i)for (int j = i + 1; j < m; ++j)cin >> wow[i][j];dfs(0);cout << ans << endl;return 0;
}

题:https://codeforces.com/problemset/problem/616/C
题意:给出n * m大小的只有‘ * ’和‘ . ’的矩阵,分别计算每一个’ * ‘的连通’ . ‘,当计算该’ * ‘时,可将该’ * ‘视为’ . ‘。
思路:首先预处理一下,每个’ . ‘的连通块计算出有多少并且标记,然后再分别处理每个’ * '四个方向的标记,如果该标记未出现过则加进ans。

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long
#define endl '\n' #define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 1e3 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;
const double eps = 1e-8;   //一般比小数点的位数至少多 2 int n, m, tmp, cnt = 0;
char wow[N][N];
bool vis[N][N];
int hh[N][N], num[N * N];
map <int, int> mp;void dfs(int x, int y)
{hh[x][y] = cnt;vis[x][y] = 1;for (int i = 0; i < 4; ++i)if (x + dx[i] >= 0 && x + dx[i] < n && y + dy[i] >= 0 && y + dy[i] < m && wow[x + dx[i]][y + dy[i]] == '.' && !vis[x + dx[i]][y + dy[i]]){tmp++;dfs(x + dx[i], y + dy[i]);}
}signed main()
{scanf("%d%d", &n, &m);for (int i = 0; i < n; ++i)scanf("%s", wow[i]);for (int i = 0; i < n; ++i)for (int j = 0; j < m; ++j)if (wow[i][j] == '.' && !hh[i][j]){tmp = 1;cnt++;dfs(i, j);num[cnt] = tmp;}for (int i = 0; i < n; ++i){for (int j = 0; j < m; ++j)if (wow[i][j] == '*'){int ans = 0;for (int k = 0; k < 4; ++k)if (i + dx[k] >= 0 && i + dx[k] < n && j + dy[k] >= 0 && j + dy[k] < m && hh[i + dx[k]][j + dy[k]]){if (!mp[hh[i + dx[k]][j + dy[k]]]){ans += num[hh[i + dx[k]][j + dy[k]]];mp[hh[i + dx[k]][j + dy[k]]]++;}}printf("%d", (ans + 1) % 10);mp.clear();}elseprintf(".");puts("");}   return 0;
}

组合数学——隔板法

题:https://ac.nowcoder.com/acm/contest/30184/L
题意:给出每个数在 1~1000 之间的单调不增序列,其中有一些数字丢失了,找出有多少方案满足该序列要求,答案对1000000007取模。

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
//#define int long long#define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}const int N = 1e6 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;int a[N];
LL f[N];void init() //预处理
{f[0] = f[1] = 1;for (int i = 2; i <= 1e6; ++i)f[i] = (f[i - 1] * i) % mod;
}LL C(int n, int m) //排列组合
{if (m == 0)return 1;return (f[n] * fastpow(f[n - m] * f[m] % mod, mod - 2, mod) % mod) % mod;    //乘法逆元
}signed main()
{   init();int n;scanf("%d", &n);for (int i = 1; i <= n; ++i)scanf("%d", &a[i]);int cnt = 0, id = 0;LL ans = 1;a[0] = 1000;for (int i = 1; i <= n; ++i){if (!a[i])cnt++;    //小球else{int n = cnt;int m = a[id] - a[i] + 1;   //盒子id = i;cnt = 0;ans = ans * (C(n + m - 1, m - 1) % mod) % mod;}          }if (cnt)   //末尾数处理{int n = cnt, m = a[id];ans = ans * C(n + m - 1, m - 1) % mod;}printf("%lld\n", ans % mod);return 0;
}

离散化 + 树状数组

题:https://www.acwing.com/problem/content/4319/
题意:

#include <iostream>
#include <cstdio>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <algorithm>
#include <set>
#include <bitset>
#include <unordered_set>
#include <memory.h>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <unordered_map>  #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define x first
#define y second
#define all(a) a.begin(), a.end()
#define int long long#define bug(a) cout << a << " *bug1*" << endl
#define bugg(a, b) cout << a << " " << b << " *bug2*" << endl
#define buggg(a, b, c) cout << a << " " << b << " " << c << " *bug3*" << endlusing namespace std;typedef long long LL;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};LL fastpow(LL b, LL k, LL p)
{LL res = 1;while (k){if (k & 1)res = res * 1LL * b % p;b = b * 1LL * b % p;k >>= 1;}//bug(res);return res % p;
}int lowbit(int x)
{return x & -x;
}const int N = 1e6 + 10, mod = 1e9 + 7, INF = 0x3f3f3f3f;int n, m;
int s[N];
int tr[N];
vector <int> nums;void add(int x, int k)  //树状数组修改操作
{for (int i = x; i < N; i += lowbit(i))tr[i] += k;
}int sum(int x) //树状数组查询操作
{int res = 0;for (int i = x; i; i -= lowbit(i))res += tr[i];return res;
}int get(int x) //二分获取离散化之后的下标
{return lower_bound(all(nums), x) - nums.begin() + 1;
}signed main()
{   scanf("%lld%lld", &n, &m);for (int i = 1; i <= n; ++i){scanf("%lld", &s[i]);s[i] += s[i - 1];  //前缀和}for (int i = 0; i <= n; ++i)   //将所有前缀和以及后续询问用到的数值全部离散化{nums.push_back(s[i]);nums.push_back(s[i] - m);}sort(all(nums));nums.erase(unique(all(nums)), nums.end());int res = 0;add(get(s[0]), 1);   //将 0 这个位置的前缀和加入树状数组for (int i = 1; i <= n; ++i){//sum(1000000) 整个值域上所有值的总个数 //sum(get(s[i]−m)) 表示所有 i 之前的前缀和中小于等于 get(s[i]−m) 的前缀和的个数res += sum(1e6) - sum(get(s[i] - m));    //答案累加上树状数组中大于 sum[r] - t 的总个数add(get(s[i]), 1);    // sum[r] 这个位置的个数加上 1 ,方便后续的计算//枚举右端点,右端点不减1,左端点减1// sum(r) - sum(l-1) < t 即 sum(l-1) > sum(r) - t       }printf("%lld\n", res);return 0;
}

一些因吹斯汀的题目记录相关推荐

  1. JavaScript预解析、作用域题目记录

    JavaScript预解析.作用域题目记录 写出以下题目执行的结果及过程分析 function fun ( n ) {console.log( n );var n = 456;console.log( ...

  2. 自用PTA题目记录0024

    自用PTA题目记录0024 以下题目序号并无实际意义 文章目录 自用PTA题目记录0024 9-2 A+B的文本文件版 代码 总结 9-2 A+B的文本文件版 题目作者: 翁恺 单位: 浙江大学 内存 ...

  3. 【面试题目】2019年中心面试题目记录

    网络上能找到流传出来的中心面试题目记录 大数据是什么? 云计算的理解? 单位涉密应该怎么做? 对于一些名词的解释:拒绝服务攻击.网络冒仿.网络蠕虫.网页恶意代码.木马主机.网络篡改 什么是物联网? 你 ...

  4. 自用PTA题目记录0001

    自用PTA题目记录0001 以下题目序号并无实际意义 文章目录 自用PTA题目记录0001 7-1 检查密码 代码 总结 7-1 检查密码 题目作者: 陈越 单位: 浙江大学 代码长度限制: 16 K ...

  5. 自用PTA题目记录0025

    自用PTA题目记录0025 以下题目序号并无实际意义 文章目录 自用PTA题目记录0025 10-1 查询图书表中全部图书的最高售价.最低售价和平均售价 代码 总结 10-1 查询图书表中全部图书的最 ...

  6. 自用PTA题目记录0023

    自用PTA题目记录0023 以下题目序号并无实际意义 文章目录 自用PTA题目记录0023 9-1 JAVA文件读写A+B题 代码 总结 9-1 JAVA文件读写A+B题 题目作者: zouxuxia ...

  7. LeetCode数据库SQL题目记录(难度:简单)

    难度:简单 目录 175. 组合两个表 176. 第二高的薪水 181. 超过经理收入的员工 182. 查找重复的电子邮箱 183. 从不订购的客户 196. 删除重复的电子邮箱 197. 上升的温度 ...

  8. 【题目记录】——The 2021 ICPC Asia Jinan Regional Contest

    文章目录 C Optimal Strategy 组合数 H Game Coin K Search For Mafuyu 欧拉序列 题目集地址 The 2021 ICPC Asia Jinan Regi ...

  9. CTF题目记录2(图片隐写)

    网上找了一个图片隐写的练习,故记录一下 题目1 png图片–LSB隐写 习惯性要先查看属性–没收获 然后stegsolve 我当然是用data extract查看了各个通道的最后两位情况,并保存了几个 ...

最新文章

  1. linux 信号软中断的方式
  2. python文件操作举例
  3. 精通python要多久-精通python 或者R语言大约需要多长时间?怎样算精通?
  4. SqlSugar ORM 入门到精通【一】入门篇
  5. Django--视图函数
  6. Warning: Attempt to present on whose view is not in模态跳转问题
  7. 三种嵌入式操作系统的分析与比析
  8. Android 编程下的四大组件之服务(Service)
  9. 机器学习篇—大厂笔试题
  10. 【CCCC】L2-028 秀恩爱分得快 (25分),模拟题
  11. uniapp底部导航栏中间凸起_PPT导航栏,真的非常好用!
  12. cad户型图练习_我的房子我做主 篇一:技多不压身—业内人士手把手教你学会用CAD绘制户型图...
  13. Seaweedfs的安装和使用
  14. 弘辽科技:抖加投放后会增粉吗?有什么技巧?
  15. excel换行按什么键_excel中关于自动换行和强制换行那些事儿
  16. 世界杯为战斗民族的历史再添荣耀与光辉_数字体验_新浪博客
  17. ZeroTier 和 FRP 速度对比实验(附搭建方法)
  18. 小米book pro16笔记本怎么U盘安装系统教学分享
  19. 冒泡排序-java版
  20. Mybatis 动态切换数据库

热门文章

  1. 大一计算机应用基础学什么,2017大学计算机应用基础试题
  2. 论文查重标题写错了怎么办?
  3. 首席工程师揭秘:LinkedIn大数据后台是如何运作的
  4. 车载毫米波雷达的性能标准与测试方法
  5. vs2019 未知错误解决方法
  6. LXD使用踩过的坑1——网络配置(后续遇到坑再更新......)
  7. 只因小黑子的HTML入土过程第五章
  8. 鸿蒙系统是谎言,鸿蒙系统可能是一个善意的谎言,任正非把余承东立的flag拆了...
  9. 网络基础学习:布线、计算机数制
  10. mapreduce 中文版 中文翻译