训练赛记录----冲冲冲

比赛名称做题数补题数
ACM-ICPC 2018 徐州赛区网络预赛4/110/7
Wannafly挑战赛13/51/2
2019上海区域赛4/130/9

第一次训练

在计蒜客上复现了 ACM-ICPC 2018 徐州赛区网络预赛

I题:是签到题,注意一些特殊情况,例如全0

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define PI acos(-1)
#define eps 1e-5
#define rint register int
using namespace std;
typedef long long LL;
typedef pair<LL, int> pli;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef pair<double, double> pdd;
typedef map<char, int> mci;
typedef map<string, int> msi;
template<class T>
void read(T &res) {
  int f = 1; res = 0;
  char c = getchar();
  while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
  while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); }
  res *= f;
}
const int INF = 0x3f;
const int N = 1010;
const int M = 410;
const int Mod = 19650827;
string s;
int main() {
  int t; cin >> t;
  int n, res;
  char c;
  while(t--) {
    cin >> n >> c >> s; 
    res = 1;
    for(int i = 0, mid, f = 0; i < n; ++i) {
      mid = abs(s[i]-c);
      if(mid || f) ++f;
      if(f == 1) res = mid < 10 ? 1 : 2;
      else if(f > 1) res += 2;
    }
    cout << res << "\n";
  }
  return 0;
}

F题:对一个二元组离散化之后暴力求答案即可

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
vector< pii > v;
vector<int> g[500005];
vector<pii> G[500005];
int getid(pii x) {
  return lower_bound(v.begin(), v.end(), x) - v.begin();
}
int main() {
  int t, n;read(t);
  pii c;
  while(t--) {
    read(n);
    _for(0, n, i) g[i].clear(), G[i].clear(); v.clear();
    _for(0, n, i) {
      int m; read(m);
      while(m--) {
        read(c.fi); read(c.se);
        G[i].push_back(c); v.push_back(c);
      }
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    _for(0, n, i) {
      for(auto it : G[i]) {
        int id = getid(it);
        if(g[id].empty() || g[id][g[id].size()-1] != i)g[id].push_back(i);
      }
    }
    int ans = 0;
    _for(0, n, i) {
      if(g[i].empty()) break;
      int Max = 1, len = 1;
      for(int j = 1; j < g[i].size(); j++) {
        if(g[i][j-1] + 1 == g[i][j]) {
          len++;
          Max = max(Max, len);
        }else len = 1;
      }
      ans = max(Max, ans);
    }
    cout << ans << endl;
  }
}

G题:先考虑平行与x轴的直线,按时间倒序来维护不同高度下的直线所延伸的长度,加入一条直线时我们判断一下大于这个高度的直线中最长的那一条是多少,若最长的那一条大于这一条,则说明这条完全被遮住了,反之会露出比最长那一条多出来的部分。再同理处理平行于y轴的直线即可。这个性质可以用线段树维护区间最值,数据比较大要先离散化,答案要开long long。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 5e5+5;
vector<int> v;
int getid(int x) {
  return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
int T[N<<2];
void up(int rt) {
  T[rt] = max(T[rt<<1|1], T[rt<<1]);
}
void upd(int rt, int l, int r, int pos, int val) {
  if(l == r) {
    T[rt] = max(T[rt], val);
    return ;
  }
  int mid = l + r >> 1;
  if(pos <= mid) upd(lson, pos, val);
  else upd(rson, pos, val);
  up(rt);
}
int qry(int rt, int l, int r, int L, int R) {
  if(l >= L && r <= R) { 
    return T[rt];
  } 
  int mid = l + r >> 1;
  int ans = 0;
  if(L <= mid) ans = qry(lson, L, R);
  if(mid <  R) ans = max(ans, qry(rson, L, R));
  return ans;
} 
int X[N], Y[N];
int main() {
  int n; read(n);
  for(int i = 1; i <= n; i++) {
    read(X[i]);read(Y[i]);
    v.push_back(X[i]);
    v.push_back(Y[i]);
  }
  sort(v.begin(), v.end());
  v.erase(unique(v.begin(), v.end()), v.end());
  int len = v.size();
  LL ans = 0;
  for(int i = n; i >= 1; i--) {
    int id = getid(Y[i]);
    int Max = qry(1, 1, len, id, len);
    ans += max(0, X[i] - Max);
    upd(1, 1, len, id, X[i]);
  }
  memset(T, 0, sizeof T);
  for(int i = n; i >= 1; i--) {
    int id = getid(X[i]);
    int Max = qry(1, 1, len, id, len);
    ans += max(0, Y[i] - Max);
    upd(1, 1, len, id, Y[i]);
  }
  cout << ans << endl;
}

H题:比较简单的线段树,可以画个图,发现每次取的是一个三角形,我们考虑每个数最多出现的次数,a[1]*n, a[2] *(n-1)…a[n]*1,实际上答案就是在这个大三角形中取出一部分再减掉一个矩形,用线段树维护两个变量即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 1e5+5;
LL T[N<<2], T1[N<<2];
int n;
void up(int rt) {
  T[rt] = T[rt<<1] + T[rt<<1|1];
  T1[rt] = T1[rt<<1] + T1[rt<<1|1];
}
void build(int rt, int l ,int r) {
  if(l == r) {
    read(T1[rt]);
    T[rt] = T1[rt] * (n-l+1);
    return ;
  }
  int mid = l + r >> 1;
  build(lson); build(rson);
  up(rt);
}
void upd(int rt, int l, int r, int pos, LL val) {
  if(l == r) {
    T1[rt] = val;
    T[rt] = T1[rt] * (n-l+1);
    return ;
  }
  int mid = l + r >> 1;
  if(pos <= mid) upd(lson, pos, val);
  else upd(rson, pos, val);
  up(rt);
}
void qry(int rt, int l, int r, int L, int R, LL& ans) {
  if(L <= l && r <= R) {
    ans += T[rt];
    ans -= T1[rt] * (n - R);
    return ;
  }
  int mid = l + r >> 1;
  if(L <= mid) qry(lson, L, R, ans);
  if(R  > mid) qry(rson, L, R, ans);
}
int main() {
  int m; read(n); read(m);
  build(1,1,n);
  int l, r, op;
  LL ans;
  while(m--) {
    scanf("%d %d %d", &op, &l, &r);
    if(op == 1) {
      ans = 0;
      qry(1, 1, n, l, r, ans);
      printf("%lld\n", ans);
    }else {
      upd(1,1,n,l,r);
    }
  }
}

赛后反思:读题是硬伤,只能靠两个队友读题,我在旁边摸鱼。还好有两道数据结构题抬了一手,H题也是想了很久才发现的,走了很多误区。还有两道dp大山没有翻过。有一道莫比乌斯反演没有时间了,没推出来,也是挺遗憾的,有时间把它补掉。最近有点混了,这样下去很难搞出成绩。希望快点开学吧。

第二次训练

在牛客上复现了 Wannafly挑战赛1

A题 :签到题,树上深度差为偶数的对数

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 2e5+5;
struct node {
  int to, next;
}e[N];
LL dep[N];
int head[N], cnt;
void add(int u, int v) {
  e[++cnt] = node {v, head[u]};
  head[u] = cnt;
  e[++cnt] = node {u, head[v]};
  head[v] = cnt;
}
int Max;
void dfs(int u, int fa, int de) {
  dep[de]++;
  Max = max(Max, de);
  for(int i = head[u]; i; i = e[i].next) {
    int v = e[i].to;
    if(v == fa) continue;
    dfs(v, u, de+1);
  }
}
LL dp[2];
int main() {
  int n, u, v;; read(n);
  _for(1, n , i) {
    read(u); read(v);
    add(u, v);
  }
  dfs(1, 0, 0);
  LL ans = 0;
  for(int i = 0; i <= Max; i++) {
    ans += dep[i] *  (dep[i] - 1) / 2 + dep[i] * dp[i&1];
    dp[i&1] += dep[i];
  }
  cout << ans << endl;
}

B题 :数据很小,先暴力求出所有区间的取值,两个区间[l1,r1], [l2, r2],先删除所有以r1开头是区间,在加上所有以r1结尾的区间的异或和相等的数量即可

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
int d[500000];
int a[100000];
int main() {
  int n;read(n);
  _rep(1, n, i) read(a[i]);
  _rep(1, n, i) {
    int k = a[i];
    d[k]++;
    for(int j = i-1; j >= 1; j--) d[k^=a[j]]++;
  }
  LL ans = 0;
  _rep(1, n, i) {
    int k = a[i]; d[k]--;
    _rep(i+1, n ,j) d[k^=a[j]]--;
    k = a[i];
    ans += d[k];
    for(int j = i-1; j >= 1; j--) ans += d[k^=a[j]];
  }
  cout << ans << endl;
}

C题 :大胆猜想小心求证之后发现答案是集合中两个距离最大的点的距离加1再除2,再大胆猜想小心求证之后发现其中一个点是深度最大的一个点,然后lca求最大的距离即可

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 3e5+5;
struct node {
  int to, next;
}e[N*2];
int head[N], cnt;
void add(int u, int v) {
  e[++cnt] = node {v, head[u]};
  head[u] = cnt;
  e[++cnt] = node {u, head[v]};
  head[v] = cnt;
}
int dep[N], f[N][25], lg[N];
void dfs(int u, int fa) {
  f[u][0] = fa; dep[u] = dep[fa] + 1;
  for(int i = 1; i <= lg[dep[u]]; i++) 
    f[u][i] = f[f[u][i-1]][i-1];
  for(int i = head[u]; i ; i = e[i].next) 
    if(e[i].to != fa) dfs(e[i].to, u);
}
int lca(int u, int v) {
  if(dep[v] < dep[u]) swap(u, v);
  while(dep[u] < dep[v]) v = f[v][lg[dep[v]-dep[u]] - 1];
  if(u == v) return u;
  for(int i = lg[dep[u]]-1; i >= 0; i--) 
    if(f[u][i] != f[v][i]) 
      u = f[u][i], v = f[v][i];
  return f[u][0];
}
int S[N];
int main() {
  int n, q;read(n); 
  for(int i = 1, u, v; i < n; i++) {
    read(u); read(v);
    add(u, v);
  }
  for(int i = 1; i <= n; i++) lg[i] = lg[i-1] + (1 << lg[i-1] == i);
  read(q);
  dfs(1, 0);
  while(q--) {
    int n; read(n);
    int u = 0, deepth = -1;
    _rep(1, n, i) {
      read(S[i]);
      if(dep[S[i]] > deepth) {
        deepth = dep[S[i]];
        u = S[i];
      }
    }
    int Max = 0;
    _rep(1, n, i) {
      Max = max(Max, deepth + dep[S[i]] - 2*dep[lca(u, S[i])]);
    }
    printf("%d\n", (Max+1)/2);
  }
} 

E题:比较遗憾,没有想出怎么用线性基求出所有可能出现的数。可以发现把一个数u从S转移到T,要异或所有和u有关的边的权值,这个好证明。然后再用线性基搞一下就可以。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 1e5+5;
int b[N], f[35];
int main() {
  int n, m; read(n); read(m);
  for(int i = 1, u, v, w; i <= m; i++) {
    scanf("%d %d %d", &u, &v, &w);
    b[u] ^= w;
    b[v] ^= w;
  }
  int cnt = 0;
  LL ans = 0;
  for(int i = 1; i <= n; i++) {
    ans |= b[i];
    for(int j = 29; j >= 0; j--) {
      if(b[i] & (1 << j)) {
        if(!f[j]) {
          f[j] = b[i];
          cnt++;
          break;
        }
        b[i] ^= f[j];
      }
    }
  }
  ans <<= cnt-1;
  while(ans >= 1000000000) ans /= 10;
  cout << ans << endl;
}

第三次训练

B题 判断有没有字符串是某个串的前缀,字典树瞎搞就可以

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 1e5+5;
int T[N][10], cnt;
bool endd[N];
int flag;
char s[15];
void insert() {
  if(flag) return ;
  int k, now = 0, len = strlen(s);
  for(int i = 0; i < len - 1; i++) {
    k = s[i] - '0';
    if(!T[now][k]) T[now][k] = ++cnt;
    now = T[now][k];
    if(endd[now]) flag = 1;
  }
  k = s[len-1]-'0';
  if(!T[now][k]) {
    T[now][k] = ++cnt;
    endd[cnt] = 1;
  }
  else flag = 1; 
}
int main() {
  int t; read(t);
  for(int ca = 1; ca <= t; ca++) {
    int n; read(n);
    memset(T, 0, sizeof T);
    memset(endd, 0, sizeof endd);
    flag = 0;
    cnt = 0;
    while(n--) {
      scanf("%s", s);
      insert();
    }
    if(flag) printf("Case #%d: No\n", ca);
    else printf("Case #%d: Yes\n", ca);
  } 
} 

D题
删除完全图的边,每个点只走一次,走完就删,求可以走多少次。
秘籍,反复横跳

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
int main() {
  int t; read(t);
  for(int id = 1; id <= t; id++) {
    int n; read(n);
    printf("Case #%d: %d\n", id, n/2);
    for(int i = 1; i <= n/2; i++) {
      int f = 1;
      int u = i-1;
      for(int j = 1; j < n; j++) {
        int v = (u + j * f + n) % n;
        printf("%d %d\n", u+1, v+1);
        f *= -1;
        u = v;
      }
    }
  }
}

F题
树剖+线段树

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 1e5+5;
struct node {
  int to, next;
}e[N<<1];
int head[N], cnt;
void add(int u, int v) {
  e[++cnt] = node {v, head[u]};
  head[u] = cnt;
  e[++cnt] = node {u, head[v]};
  head[v] = cnt;
}
int fath[N], dep[N], size[N], wson[N];
void dfs1(int u) {
  size[u] = 1;
  for(int i = head[u]; i; i = e[i].next) {
    int v = e[i].to;
    if(v == fath[u]) continue;
    fath[v] = u;
    dep[v] = dep[u] + 1;
    dfs1(v);
    size[u] += size[v];
    if(size[v] > size[wson[u]]) wson[u] = v;
  }
}
int tops[N], dfn[N], fdfn[N];
void dfs2(int u, int TP) {
  dfn[u] = ++cnt;
  fdfn[cnt] = u;
  tops[u] = TP;
  if(wson[u]) dfs2(wson[u], TP);
  for(int i = head[u]; i; i = e[i].next) {
    int v = e[i].to;
    if(v == fath[u] || v == wson[u]) continue;
    dfs2(v, v);
  }
}
void init(int n) {
  cnt = 0;
  memset(head, 0, 4*(n+1));
  memset(fath, 0, 4*(n+1));
  memset(wson, 0, 4*(n+1));
}
const LL Mod = 1e9+7;
struct node1{
  LL l, r, add, mul, set, p1,p2,p3;
  LL mid() {return l + r >> 1; }
}T[N<<2];
LL f[N];
void up(int rt) {
  T[rt].p1 = (T[rt<<1].p1 + T[rt<<1|1].p1) % Mod;
  T[rt].p2 = (T[rt<<1].p2 + T[rt<<1|1].p2) % Mod;
  T[rt].p3 = (T[rt<<1].p3 + T[rt<<1|1].p3) % Mod;
}
void calset(int rt) {
  LL len2 = T[rt<<1|1].r - T[rt<<1|1].l + 1;
  LL len1 = T[rt<<1].r - T[rt<<1].l + 1;
  
  T[rt<<1|1].set = T[rt<<1].set = T[rt].set;
  T[rt<<1|1].add = T[rt<<1].add = 0;
  T[rt<<1|1].mul = T[rt<<1].mul = 1;
  
  T[rt<<1|1].p1 = len2 * (T[rt].set) % Mod;
  T[rt<<1|1].p2 = T[rt<<1|1].p1 * T[rt].set % Mod;
  T[rt<<1|1].p3 = T[rt<<1|1].p2 * T[rt].set % Mod;

  T[rt<<1].p1 = len1 * (T[rt].set) % Mod;
  T[rt<<1].p2 = T[rt<<1].p1 * T[rt].set % Mod;
  T[rt<<1].p3 = T[rt<<1].p2 * T[rt].set % Mod;

  T[rt].set = -1;
}
void calmul(int rt) {
  LL &c = T[rt].mul;
  
  T[rt<<1|1].mul = (T[rt<<1|1].mul * c) % Mod;
  if(T[rt<<1|1].add) T[rt<<1|1].add = (T[rt<<1|1].add * c) % Mod;
  T[rt<<1|1].p1 = T[rt<<1|1].p1 * c % Mod;
  T[rt<<1|1].p2 = T[rt<<1|1].p2 * c % Mod * c % Mod;
  T[rt<<1|1].p3 = T[rt<<1|1].p3 * c % Mod * c % Mod * c % Mod;

  T[rt<<1].mul = (T[rt<<1].mul * c) % Mod;
  if(T[rt<<1].add) T[rt<<1].add = (T[rt<<1].add * c) % Mod;
  T[rt<<1].p1 = T[rt<<1].p1 * c % Mod;
  T[rt<<1].p2 = T[rt<<1].p2 * c % Mod * c % Mod;
  T[rt<<1].p3 = T[rt<<1].p3 * c % Mod * c % Mod * c % Mod;

  c = 1;
}
void caladd(int rt) {
  LL &c = T[rt].add;
  LL len2 = T[rt<<1|1].r - T[rt<<1|1].l + 1;
  LL len1 = T[rt<<1].r - T[rt<<1].l + 1;
  T[rt<<1|1].add = (c + T[rt<<1|1].add) % Mod;
  
  T[rt<<1].add = (c + T[rt<<1].add) % Mod;
  
  LL temp = c * c % Mod * c % Mod;
  T[rt<<1|1].p3 = (T[rt<<1|1].p3 + temp * len2 + 3 * c * ((T[rt<<1|1].p2 + T[rt<<1|1].p1 * c) % Mod)) % Mod;
  T[rt<<1|1].p2 = (T[rt<<1|1].p2 + c * c % Mod * len2 % Mod + 2 * T[rt<<1|1].p1 * c % Mod) % Mod;
  T[rt<<1|1].p1 = (T[rt<<1|1].p1 + c * len2 % Mod) % Mod;

  T[rt<<1].p3 = (T[rt<<1].p3 + temp * len1 + 3 * c * ((T[rt<<1].p2 + T[rt<<1].p1 * c) % Mod)) % Mod;
  T[rt<<1].p2 = (T[rt<<1].p2 + c * c % Mod * len1 % Mod + 2 * T[rt<<1].p1 * c % Mod) % Mod;
  T[rt<<1].p1 = (T[rt<<1].p1 + c * len1 % Mod) % Mod;
  
  c = 0;
}
void down(int rt) {
  if(~T[rt].set) calset(rt);
  if(T[rt].mul != 1) calmul(rt);
  if(T[rt].add) caladd(rt);
}
void build(int rt, int l, int r) {
  T[rt].l = l; T[rt].r = r;
  T[rt].mul = 1; T[rt].add = 0;
  T[rt].set = -1;
  if(l == r) {
    T[rt].p1 = f[fdfn[l]];
    T[rt].p2 = T[rt].p1 * f[fdfn[l]] % Mod;
    T[rt].p3 = T[rt].p2 * f[fdfn[l]] % Mod;
    return ;
  }
  int mid = l + r >> 1;
  build(lson);  build(rson);  up(rt);
}
void upd(int rt, LL L, LL R, int flag, LL c) {
  if(T[rt].l >= L && T[rt].r <= R) {
    if(flag == 1) {
      T[rt].set = c;
      T[rt].add = 0;
      T[rt].mul = 1;
      T[rt].p1 = (T[rt].r - T[rt].l + 1) * c %  Mod;
      T[rt].p2 = T[rt].p1 * c % Mod;
      T[rt].p3 = T[rt].p2 * c % Mod;
    }else if(flag == 2) {
      T[rt].add = (T[rt].add + c) % Mod;
      LL temp = c * c % Mod * c % Mod * (T[rt].r - T[rt].l + 1) % Mod;
      T[rt].p3 = (T[rt].p3 + temp + 3 * c * ((T[rt].p2 + T[rt].p1 * c) % Mod)) % Mod;
      T[rt].p2 = (T[rt].p2 + c * c % Mod * (T[rt].r - T[rt].l + 1) % Mod + 2 * T[rt].p1 * c % Mod) % Mod;
      T[rt].p1 = (T[rt].p1 + c * (T[rt].r - T[rt].l + 1) % Mod) % Mod;
    }else {
      T[rt].mul = (T[rt].mul * c) % Mod;
      if(T[rt].add) T[rt].add = (T[rt].add * c) % Mod;
      T[rt].p1 = T[rt].p1 * c % Mod;
      T[rt].p2 = T[rt].p2 * c % Mod * c % Mod;
      T[rt].p3 = T[rt].p3 * c % Mod * c % Mod * c % Mod;
    }
    return ;
  }
  down(rt);
  LL mid = T[rt].mid();
  if(L <= mid) upd(rt<<1, L, R, flag, c);
  if(R >  mid) upd(rt<<1|1, L, R, flag, c);
  up(rt);
}
LL qry(int rt, LL L, LL R) {
  if(T[rt].l >= L && T[rt].r <= R) {
    return T[rt].p3;
  }
  LL ans = 0;
  down(rt);
  int mid = T[rt].mid();
  if(L <= mid) ans = qry(rt<<1, L, R);
  if(R >  mid) ans += qry(rt<<1|1, L, R); 
  return ans % Mod;
}
void upd(int u, int v, int flag, LL c) {
  while(tops[u] != tops[v]) {
    if(dep[tops[u]] < dep[tops[v]]) swap(u, v);
    upd(1, dfn[tops[u]], dfn[u], flag, c);
    u = fath[tops[u]];
  }
  if(dfn[u] > dfn[v]) swap(u, v);
  upd(1, dfn[u], dfn[v], flag, c);
}
LL qry(int u, int v) {
  LL ans = 0;
  while(tops[u] != tops[v]) {
    if(dep[tops[u]] < dep[tops[v]]) swap(u, v);
    ans += qry(1, dfn[tops[u]], dfn[u]);
    ans %= Mod;
    u = fath[tops[u]];
  }
  if(dfn[u] > dfn[v]) swap(u, v);
  ans += qry(1, dfn[u], dfn[v]);
  return ans % Mod;
}
int main() {
  int t; read(t);
  for(int id = 1; id <= t; id++) {
    printf("Case #%d:\n", id);
    int n; read(n);
    init(n);
    for(int i = 1, u, v; i < n; i++) {
      read(u); read(v);
      add(u, v);
    }
    _rep(1, n, i) read(f[i]);
    dfs1(1);
    cnt = 0;
    dfs2(1,1);
    build(1,1,n);
    int q, op, l, r;
    LL c;
    read(q);
    while(q--) {
      scanf("%d %d %d", &op, &l, &r) ;
      if(op == 4) printf("%lld\n", qry(l, r));
      else {
        read(c);
        upd(l, r, op, c);
      }
    }
  }
}
/*
2
5
2 1
1 3
5 3
4 3
1 2 3 4 5
6
4 2 4
1 5 4 2
2 2 4 3
3 2 3 4
4 5 4
4 2 4
5
2 1
1 3
5 3
4 3
1 2 3 4 5
6
4 2 4
1 5 4 2
2 2 4 3
3 2 3 4
4 5 4
4 2 4
*/

K题
强哥写的,没怎么写这题

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define pii pair<int, int>
#define mp(a, b) make_pair(a, b)
#define piii pair<pii, int>
#define ufor(a, b, i) for (register int i = (a); i <= (b); ++i)
#define dfor(a, b, i) for (register int i = (a); i >= (b); --i)
using namespace std;
inline ll read() {
	ll x = 0, f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
const int N = 1e5+5;
int T, n, m, cnt, ans;
int f[256], t[256];
int main() {
  T = read();
  ufor(1, T, k) {
    n = read(); m = read();
    ans = 0;
    ufor(1, m, i)
      f[i] = read(), t[i] = read();
    for (int i = 0; i < (1 << n); ++i) {
      cnt = 0;
      ufor(1, m, j)
        if (((i >> f[j] - 1) & 1) != ((i >> t[j] - 1) & 1)) cnt++;
      ans = max(ans, cnt);
    }
    printf("Case #%d: %d\n", k, ans);
  }
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值