Codeforces round #321 (DIV. 2)

来源:互联网 发布:淘宝商品资质要填吗 编辑:程序博客网 时间:2024/05/16 10:33

题解链接:http://www.cygmasot.com/index.php/2015/09/23/codeforces_580/

链接

A:Kefa and First Steps

题意:the length of the maximum non-decreasing subsegment

直接搞,水题

#include <cstring> #include <iostream>  #include <algorithm>  #include <cstdio>  #include <map>#include <queue>#include <set>using namespace std;template <class T>inline bool rd(T &ret) {char c; int sgn;if (c = getchar(), c == EOF) return 0;while (c != '-' && (c<'0' || c>'9')) c = getchar();sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');ret *= sgn;return 1;}template <class T>inline void pt(T x) {if (x <0) {putchar('-');x = -x;}if (x>9) pt(x / 10);putchar(x % 10 + '0');}  typedef long long ll;typedef pair<int, int> pii;const int inf = 1e9;const int N = 1e5+10;int n; int a[N];int main() {rd(n);for (int i = 1; i <= n; i++)rd(a[i]);int ans = 1;for (int i = 2, pre = 1; i <= n; i++) {if (a[i] >= a[i - 1]) {pre++;}else pre = 1;ans = max(ans, pre);}pt(ans);return 0;}


B:Kefa and Company

题意:有一个双关键字的数组,共n个元素。常数d
选任意个使得选出的元素中 第一关键字(最大的-最小的)<d
并且使得第二关键字和最大。
问:最大的和是多少。
思路:
先排个序,然后two pointers搞搞,枚举左端点,右端点是单调的。

#include <cstring> #include <iostream>  #include <algorithm>  #include <cstdio>  #include <map>#include <queue>#include <set>using namespace std;template <class T>inline bool rd(T &ret) {char c; int sgn;if (c = getchar(), c == EOF) return 0;while (c != '-' && (c<'0' || c>'9')) c = getchar();sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');ret *= sgn;return 1;}template <class T>inline void pt(T x) {if (x <0) {putchar('-');x = -x;}if (x>9) pt(x / 10);putchar(x % 10 + '0');}  typedef long long ll;typedef pair<int, int> pii;const int inf = 1e9;const int N = 1e5+10;int n, d;pii a[N];ll sum[N];int main() {rd(n); rd(d);for (int i = 1; i <= n; i++) {rd(a[i].first); rd(a[i].second);}sort(a + 1, a + 1 + n);sum[0] = 0;for (int i = 1; i <= n; i++)sum[i] = sum[i - 1] + a[i].second;ll ans = a[1].second;int r = 1;for (int i = 1; i <= n; i++) {while (r+1 <= n && a[r+1].first - a[i].first < d)r++;ans = max(ans, sum[r] - sum[i - 1]);}pt(ans);return 0;}


C:Kefa and Park

题意:给定n个点的数 常数m

下面n个数给出点权(点权为0或1)

要求从根走到叶子节点的最短路径上 连续1的个数不超过m个 的叶子节点有多少个。

思路:

dfs直接搞就好了。

#include <cstring> #include <iostream>  #include <algorithm>  #include <cstdio>  #include <map>#include <queue>#include <set>using namespace std;template <class T>inline bool rd(T &ret) {char c; int sgn;if (c = getchar(), c == EOF) return 0;while (c != '-' && (c<'0' || c>'9')) c = getchar();sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');ret *= sgn;return 1;}template <class T>inline void pt(T x) {if (x <0) {putchar('-');x = -x;}if (x>9) pt(x / 10);putchar(x % 10 + '0');}  typedef long long ll;typedef pair<int, int> pii;const int inf = 1e9;const int N = 1e5+10;int n, m;int a[N];vector<int>G[N];int ans;void dfs(int u, int fa, int val) {if(a[u] == 1)val += a[u];else val = 0;if (val > m)return;if (u != fa && G[u].size() == 1){ans++;}for (auto v : G[u]) {if (v == fa)continue;dfs(v, u, val);}}int main() {rd(n); rd(m);for (int i = 1; i <= n; i++)rd(a[i]);for (int i = 1, u, v; i < n; i++) {rd(u); rd(v);G[u].push_back(v); G[v].push_back(u);}ans = 0;dfs(1, 1, 0);pt(ans);return 0;}


D:Kefa and Dishes

n个点 m条有向边 选恰好k个点

下面n个数给出点权。

下面m行给出边和边权。

设上一次选的点是u

这一次选的点是v,则可以获得边权u->v的价值。

问:使得选出的权和最大,问最大的权和。

思路:显然是状压dp

dp[i][j]表示选的点状态为i,最后一次选的点是j的最大价值。

#include <cstring> #include <iostream>  #include <algorithm>  #include <cstdio>  #include <map>#include <queue>#include <set>using namespace std;template <class T>inline bool rd(T &ret) {char c; int sgn;if (c = getchar(), c == EOF) return 0;while (c != '-' && (c<'0' || c>'9')) c = getchar();sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');ret *= sgn;return 1;}template <class T>inline void pt(T x) {if (x <0) {putchar('-');x = -x;}if (x>9) pt(x / 10);putchar(x % 10 + '0');}  typedef long long ll;typedef pair<int, int> pii;const int inf = 1e9;const int N = 20;int n, m, k;int cnt(int x) {int ans = 0;while (x) { ans += x & 1; x >>= 1; }return ans;}int a[N];int b[N][N];ll dp[1 << 18][18];bool vis[1 << 18][18];int main() {rd(n); rd(m); rd(k);for (int i = 0; i < n; i++)rd(a[i]);while (k--) {int u, v, d;rd(u); rd(v); rd(d); b[u-1][v-1] = d;}queue<pii> q;for (int i = 0; i < n; i++) {dp[1 << i][i] = a[i];q.push({ 1 << i,i });vis[1 << i][i] = 1;}ll ans = 0;while (!q.empty()) {auto u = q.front(); q.pop();if (cnt(u.first) == m) {ans = max(ans, dp[u.first][u.second]);continue;}for (int i = 0; i < n; i++) {if (!(u.first & (1 << i))){pii v = { u.first | (1 << i), i };ll now = dp[u.first][u.second] + b[u.second][i] + a[i];dp[v.first][v.second] = max(dp[v.first][v.second], now);if (!vis[v.first][v.second]) {vis[v.first][v.second] = 1;q.push(v);}}}}pt(ans);return 0;}


E:Kefa and Watch

题意:

给定n m k。

下面长度为n的数字串。

下面m+k个操作。

1 l r c:把区间[l,r]的所有字符改成c

2 l r d:询问区间[l,r]是否为周期d

(所谓周期 x 就是 (1 ≤ x ≤ |s|), if si  =  si + x for all i from 1 to |s|  -  x.)

对于每个询问输出YES or NO

思路:

首先是一个结论:若字符串s(下标为:[1,len])具有周期性x

那么 [1+x,len] == [1,len-x]

这个可以简单证明得到,不再重复证明。

因此我们需要动态获得区间的Hash值。

所以用线段树维护区间Hash值.

 

#include <cstring> #include <iostream>  #include <algorithm>  #include <cstdio>  #include <map>#include <queue>#include <set>using namespace std;template <class T>inline bool rd(T &ret) {char c; int sgn;if (c = getchar(), c == EOF) return 0;while (c != '-' && (c<'0' || c>'9')) c = getchar();sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');ret *= sgn;return 1;}template <class T>inline void pt(T x) {if (x <0) {putchar('-');x = -x;}if (x>9) pt(x / 10);putchar(x % 10 + '0');}  typedef long long ll;typedef pair<int, int> pii;const int inf = 1e8;const int MAGIC = 311, MOD = 1e9 + 7;const int N = 1e5 + 10;#define L(x) tree[x].l#define R(x) tree[x].r#define ls (id<<1)#define rs (id<<1|1)#define H(x) tree[x].hash#define La(x) tree[x].lazy#define Len(x) tree[x].lenint base[N];int p[10][N];int a[N];struct Node {int l, r, hash, lazy, len;}tree[N << 2];void up(int id) {H(id) = ((ll)H(ls) * base[Len(rs)] % MOD + H(rs)) % MOD;}void go(int id, int val) {La(id) = val;H(id) = p[val][Len(id)];}void down(int id) {if (La(id) != -1) {go(ls, La(id));go(rs, La(id));La(id) = -1;}}void build(int l, int r, int id) {L(id) = l; R(id) = r; Len(id) = r - l + 1; La(id) = -1;if (l == r) {H(id) = p[a[l]][1];return;}int mid = (l + r) >> 1;build(l, mid, ls); build(mid + 1, r, rs); up(id);}void change(int l, int r, int val, int id) {if (l == L(id) && R(id) == r) {go(id, val);return;}down(id);int mid = (L(id) + R(id)) >> 1;if (r <= mid)change(l, r, val, ls);else if (mid < l)change(l, r, val, rs);else {change(l, mid, val, ls);change(mid + 1, r, val, rs);}up(id);}int query(int l, int r, int id) {if (l == L(id) && R(id) == r) {return H(id);}down(id);int mid = (L(id) + R(id)) >> 1;int ok;if (r <= mid)ok = query(l, r, ls);else if (mid < l)ok = query(l, r, rs);else {ok = query(l, mid, ls);ok = ((ll)ok * base[r-mid] % MOD + query(mid + 1, r, rs)) % MOD;}up(id);return ok;}int n, m, k;char str[N];int main() {base[0] = 1;for (int i = 1; i < N; ++i) base[i] = ((ll)base[i - 1] * MAGIC) % MOD;for (int i = 0; i < 10; i++) {p[i][0] = 0;for (int j = 1; j < N; j++)p[i][j] = ((ll)p[i][j - 1] * MAGIC%MOD + i) % MOD;}rd(n); rd(m); rd(k);scanf("%s", str + 1);for (int i = 1; i <= n; i++)a[i] = str[i]-'0';build(1, n, 1);k += m;while (k--) {int op, l, r, c;rd(op); rd(l); rd(r); rd(c);if (op == 1) change(l, r, c, 1);else {if (l > r-c || l+c>r) { puts("YES");continue; }ll x = query(l, r - c, 1), y = query(l + c, r, 1);x == y ? puts("YES") : puts("NO");}}return 0;}

0 0