代码:
#include
using namespace std;
const int MAXN = 40;
int arr[40];
int main(){
int a, pre = 0, ans = 0;
while(cin >> a && a){
if(a == 1)
ans += 1, pre = 1;
else{
if(pre == 1 || pre == 0)
pre = 2;
else
pre += 2;
ans += pre;
}
}
cout << ans << endl;
return 0;
}
代码:
#include
using namespace std;
const int N = 110, M = 1010;
struct node{
int x, fx;
node():x{-1}, fx{1} {};
};
node arr[N];
int seats[M];
int n, L, t;
int main(){
cin >> n >> L >> t;
for(int i = 1; i <= n; i ++){
cin >> arr[i].x;
seats[arr[i].x] = i;
}
while(t --){
for(int i = 1; i <= n; i ++){
int &x = arr[i].x;
seats[x] = 0;
x += arr[i].fx;
if(x == L || x == 0)
arr[i].fx = -arr[i].fx;
if(seats[x])
arr[i].fx = -arr[i].fx, arr[seats[x]].fx = -arr[seats[x]].fx;
seats[x] = i;
}
}
for(int i = 1; i <= n; i ++)
cout << arr[i].x << " ";
return 0;
}
#include
#include
#include
using namespace std;
const int N = 110;
struct node {
string name;
vector<string> v;
bool op{}; //末尾是否有 /
node() {
op = false;
}
};
node arr[N];
int n, m;
void deal(node &a, const string &s) {
int pos = 1; //跳过第一个 /
int len;
a.op = s.back() == '/';
while (pos < s.length()) {
len = 0;
while (pos + len < s.length() && s[pos + len] != '/')
++len;
a.v.push_back(s.substr(pos, len));
pos += len + 1;
}
}
bool check(node &tmp, node &a, vector<string> &ans) {
//合法性检查
if (a.v.size() && a.v.back() != "" && a.op != tmp.op)
return false;
int pos = 0, i = 0;
for (; i < tmp.v.size() && pos < a.v.size(); i++, pos++) {
string &s = tmp.v[i];
if (a.v[pos] == s) {
continue;
} else {
if (a.v[pos] == "" ) {
for (char c : s)
if (!isdigit(c))
return false;
//去除前导 0
int k = 0;
//保留一位 考虑全部都是0的情况
while (k + 1 < s.length() && s[k] == '0')
++k;
ans.push_back(s.substr(k));
} else if (a.v[pos] == "" ) {
ans.push_back(s);
} else if (a.v[pos] == "" ) {
string t;
for (; i < tmp.v.size(); i++)
t += tmp.v[i] + '/';
if (!tmp.op)
t.pop_back();
ans.push_back(t);
return true;
} else {
return false;
}
}
}
return i == tmp.v.size() && pos == a.v.size();
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
string a, b;
cin >> a >> b;
arr[i].name = b;
deal(arr[i], a);
}
while (m--) {
node tmp;
string s;
bool op = false;
cin >> s;
deal(tmp, s);
for (int i = 0; i < n && !op; i++) {
node &a = arr[i];
vector<string> ans;
if (check(tmp, a, ans)) {
cout << a.name << " ";
for (const string &ss : ans)
cout << ss << " ";
cout << endl;
op = true;
}
}
if (!op)
cout << "404" << endl;
}
return 0;
}
代码:
#include
using namespace std;
int arr[3][3];
inline int cal() {
int cnt = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (arr[i][j] == 0)
++cnt;
return cnt;
}
//op为1代表先手
int dfs(int p) {
//判断是否获胜
int q = 3 - p;
bool op = false;
for (int i = 0; i < 3; i++) {
bool t = true;
for (int j = 0; j < 3; j++)
if (arr[i][j] != q)
t = false;
if (t)
op = true;
}
for (int i = 0; i < 3; i++) {
bool t = true;
for (int j = 0; j < 3; j++)
if (arr[j][i] != q)
t = false;
if (t)
op = true;
}
op |= (arr[0][0] == q && arr[1][1] == q && arr[2][2] == q) || (arr[2][0] == q && arr[1][1] == q && arr[0][2] == q);
if (op) {
int t = cal() + 1;
//考虑到上一个对手
return q == 1 ? t : -t;
}
//填满了
if (cal() == 0)
return 0;
int a = -10, b = 10;
//回溯dfs
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (arr[i][j])
continue;
arr[i][j] = p;
int t = dfs(3 - p);
a = max(a, t);
b = min(b, t);
arr[i][j] = 0;
}
}
if (p == 1)
return a;
else
return b;
}
int main() {
int T;
cin >> T;
while (T--) {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
cin >> arr[i][j];
cout << dfs(1) << endl;
}
return 0;
}
第三行包含 n-1 个整数,描述树的形态,其中第 i 个数 fi 表示节点 i+1 与节点 fi 之间有一条边,保证 1≤fi≤i接下来 m 行,每行包含三个整数 u,v,d,描述一个操作即将树上 u 到 v 唯一的简单路径上每个点的权值 ai 都加上 d,之后询问满足条件的两次求和的结果。保证 1≤u,v≤n,0≤d 保证上述同一行所有的数之间,均用一个空格隔开。
输出格式
输出到标准输出。
输出 m 行每行一个整数,表示两次求和的结果对 Q=1000000007 求余的结果。
子任务
共有 10 个测试点,各测试点特点如下:
测试点1:n=10,m=10。
测试点2:n=50,m=50。
测试点3:n=300,m=300。
测试点4:n=2000,m=2000。
测试点5:n=2000,m=100000。
测试点6:n=100000,m=100000。保证 fi=i。
测试点7:n=100000,m=100000。保证 fi=⌊(i+1)/2⌋,其中 ⌊⋅⌋ 表示向下取整,即给定的树是完全二叉树。
测试点8:n=100000,m=100000。保证对于同一组数据,相同的 fi 至多出现 2 次,即给定的树是二叉树。
测试点9:n=100000,m=100000。
测试点10:n=100000,m=100000。
上述约束对同一测试点中的每组数据都有效。
代码:
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 100010, M = N * 2, MOD = 1e9 + 7;
int n, m, L, R;
int w[N];
int h[N], father[N], e[M], ne[M], idx;
int depth[N], fa[N][17];
int path[N], d[N], que[N];
int pos[N], root[N];
bool st[N];
int tr[N];
struct Node
{
int d, w, id;
bool operator< (const Node& t) const
{
return d < t.d;
}
}q[N], p[N];
inline void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
inline int lowbit(int x)
{
return x & -x;
}
inline void update(int x, int v, int k)
{
for (int i = x; i <= k; i += lowbit(i)) tr[i] = (tr[i] + v) % MOD;
}
inline int query(int x, int k)
{
x = min(x, k);
int res = 0;
for (int i = x; i > 0; i -= lowbit(i)) res = (res + tr[i]) % MOD;
return res;
}
void bfs()
{
memset(depth, 0x3f, sizeof depth);
depth[0] = 0, depth[1] = 1;
int hh = 0, tt = 0;
que[0] = 1;
while (hh <= tt)
{
int t = que[hh ++ ];
for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (depth[j] > depth[t] + 1)
{
depth[j] = depth[t] + 1;
que[ ++ tt] = j;
fa[j][0] = t;
for (int k = 1; k <= 16; k ++ )
fa[j][k] = fa[fa[j][k - 1]][k - 1];
}
}
}
}
inline int lca(int a, int b)
{
if (depth[a] < depth[b]) swap(a, b);
for (int k = 16; k >= 0; k -- )
if (depth[fa[a][k]] >= depth[b])
a = fa[a][k];
if (a == b) return a;
for (int k = 16; k >= 0; k -- )
if (fa[a][k] != fa[b][k])
{
a = fa[a][k];
b = fa[b][k];
}
return fa[a][0];
}
void dfs(int u, int fa)
{
d[u] = (d[fa] + path[u]) % MOD;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j == fa) continue;
dfs(j, u);
}
}
int get_size(int u, int fa)
{
if (st[u]) return 0;
int res = 1;
for (int i = h[u]; ~i; i = ne[i])
if (e[i] != fa)
res += get_size(e[i], u);
return res;
}
int get_wc(int u, int fa, int tot, int& wc)
{
if (st[u]) return 0;
int sum = 1, ms = 0;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j == fa) continue;
int t = get_wc(j, u, tot, wc);
ms = max(ms, t);
sum += t;
}
ms = max(ms, tot - sum);
if (ms <= tot / 2) wc = u;
return sum;
}
void get_dist(int u, int fa, int dist, int sum, int& qt)
{
if (st[u]) return;
q[ ++ qt] = {dist, sum, u};
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j != fa)
get_dist(j, u, dist + 1, (sum + w[j]) % MOD, qt);
}
}
inline int get(Node a[], int k, int limit, int wu, int& pu)
{
sort(a + 1, a + k + 1);
static int sum[N];
int res = 0;
for (int i = 1; i <= k; i ++ ) sum[i] = (sum[i - 1] + a[i].w) % MOD;
for (int i = 1, j = k; i < j; i ++ )
{
while (j > i && a[j].d + a[i].d - 1 > limit) j -- ;
if (j > i && a[j].d + a[i].d - 1 <= limit)
{
res = (res + (LL)sum[j] - sum[i] + (LL)(j - i) * a[i].w - (LL)wu * (j - i)) % MOD;
pu = (pu + j - i) % MOD;
}
}
return res;
}
int dfs_path(int u, int fa, int dist, int maxd)
{
if (st[u]) return 0;
int res = (query(R + 1 - dist, maxd) - query(L - dist, maxd)) % MOD;
if (dist >= L && dist <= R) res = (res + 1) % MOD;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j != fa)
res = (res + dfs_path(j, u, dist + 1, maxd)) % MOD;
}
path[u] = (path[u] + res) % MOD;
return res;
}
int calc(int u)
{
if (st[u]) return 0;
get_wc(u, -1, get_size(u, -1), u);
st[u] = true;
int res = 0, pt = 0;
if (L <= 1 && R >= 1) res = w[u], path[u] = (path[u] + 1) % MOD;
int cnt = 0, maxd = 0;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i], qt = 0;
if (st[j]) continue;
get_dist(j, -1, 2, (w[u] + w[j]) % MOD, qt);
int pR = 0, pL = 0;
res = (res - (LL)(get(q, qt, R, w[u], pR) - get(q, qt, L - 1, w[u], pL))) % MOD;
path[u] = (path[u] - (LL)(pR - pL)) % MOD;
pos[ ++ cnt] = pt + 1; // 每一段开头
root[cnt] = j; // 每一段的根节点
for (int k = 1; k <= qt; k ++ )
{
if (q[k].d >= L && q[k].d <= R)
{
res = (res + q[k].w) % MOD;
path[u] = (path[u] + 1) % MOD; // 只计算从u到当前点的
}
p[ ++ pt] = q[k];
maxd = max(maxd, q[k].d);
}
}
pos[cnt + 1] = pt + 1; // 哨兵
for (int i = 1; i <= maxd; i ++ ) tr[i] = 0;
for (int i = 1; i <= pt; i ++ ) update(p[i].d, 1, maxd); // 插入树状数组中
for (int i = 1; i <= cnt; i ++ )
{
int l = pos[i], r = pos[i + 1] - 1;
for (int j = l; j <= r; j ++ ) update(p[j].d, -1, maxd); // 将当前子树中的节点删掉
dfs_path(root[i], u, 2, maxd);
for (int j = l; j <= r; j ++ ) update(p[j].d, 1, maxd); // 将当前子树中的节点添加回来
}
int pR = 0, pL = 0;
res = (res + (LL)get(p, pt, R, w[u], pR) - get(p, pt, L - 1, w[u], pL)) % MOD;
path[u] = (path[u] + (LL)pR - pL) % MOD;
for (int i = h[u]; ~i; i = ne[i]) res = (res + calc(e[i])) % MOD;
return res;
}
int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
scanf("%d%d%d%d", &n, &m, &L, &R);
memset(h, -1, sizeof h), idx = 0;
memset(path, 0, sizeof path);
for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
for (int i = 2; i <= n; i ++ )
{
int p;
scanf("%d", &p);
add(i, p), add(p, i);
father[i] = p;
}
memset(st, 0, sizeof st);
int res = calc(1);
dfs(1, 0);
bfs();
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
int p = lca(a, b);
int sum = (d[a] + (LL)d[b] - d[p] * 2 + path[p]) * c % MOD;
res = ((res + sum) % MOD + MOD) % MOD;
printf("%d\n", res);
}
}
return 0;
}
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/957323/
更多历年题解戳这里:ccf-csp 历年真题题解