A:

给你一个长度为n的序列,你每次可以将一个序列分割成两个连续的的子序列,
分割的代价为原序列的总和。
现在允许你在初始时将序列重新排列一次。
问分割成n个长度为1的序列的最大总代价是多少?

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;
int n, sum, a[maxn];
 
int main(){
    scanf("%d", &n);
    for(int i=1; i<=n; i++) scanf("%d", &a[i]), sum += a[i];
    sort(a+1, a+n+1);
    LL ans = 0;
    for(int i=1; i<n; i++){
        ans += sum;
        sum -= a[i];
    }
    return 0*printf("%lld\n", ans);
}

B:

精灵王国有N座美丽的城市,它们以一个环形排列在Bzeroth的大陆上。其中第i座城市到第i+1座城市花费的时间为d[i]。特别地,第N座城市到第1座城市花费的时间为d[N]。这些道路都是双向的。

另外,精灵们在数千年的时间里建造了M座传送门,第i座传送门连接了城市u[i]与城市v[i],并且需要花费w[i]的时间通过(可能有两座传送门连接了同一对城市,也有可能一座传送门连接了相同的两座城市)。这些传送门都是双向的。

小S是精灵王国交通部部长,她的职责是为精灵女王设计每年的巡查路线。每次陛下会从某一个城市到达另一个城市,沿路调查每个城市的治理情况,她需要找出一条用时最短的路线。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int maxm = 110;
typedef long long LL;
LL n, m, q, cnt, a[maxn], sum[maxn], b[maxm], dis[maxm][maxm];
LL getAns(LL x, LL y){
    if(x>y) swap(x, y);
    return min(abs(sum[y]-sum[x]), abs(sum[x]+sum[n]-sum[y]));
}
LL getid(LL x){
    return lower_bound(b+1, b+cnt+1, x) - b;
}
struct node{
    LL u,v,w;
}g[maxm];
int main(){
    scanf("%lld %lld", &n,&m);
    for(LL i=1; i<=n; i++) scanf("%lld", &a[i]);
    for(LL i=n+1; i>1; i--) a[i] = a[i-1];
    a[1] = a[n+1];
    for(LL i=1; i<=n; i++) sum[i]=sum[i-1]+a[i];
    for(LL i=1; i<=m; i++){
        scanf("%lld %lld %lld", &g[i].u,&g[i].v,&g[i].w);
        if(g[i].u==g[i].v) continue;
        b[++cnt] = g[i].u;
        b[++cnt] = g[i].v;
    }
    sort(b+1, b+cnt+1);
    cnt = unique(b+1, b+cnt+1)-b-1;
    for(LL i=1; i<=cnt; i++)
        for(LL j=1; j<=cnt; j++)
            dis[i][j] = dis[j][i] = getAns(b[i], b[j]);
    for(LL i=1; i<=m; i++){
        LL x = getid(g[i].u), y = getid(g[i].v);
        dis[x][y] = dis[y][x] = min(dis[x][y], g[i].w);
    }
    //floyd
    for(LL k=1; k<=cnt; k++)
        for(LL i=1; i<=cnt; i++)
            for(LL j=1; j<=cnt; j++)
                if(dis[i][j]>dis[i][k]+dis[k][j])
                    dis[i][j]=dis[i][k]+dis[k][j];
    scanf("%lld", &q);
    while(q--){
        LL x,y;
        scanf("%lld %lld", &x,&y);
        LL ans = getAns(x,y);
        for(LL i=1; i<=cnt; i++)
            for(LL j=1; j<=cnt; j++)
                ans = min(ans, getAns(x,b[i])+dis[i][j]+getAns(b[j],y));
        printf("%lld\n", ans);
    }
    return 0;
}

C:

给定一个n*m的矩阵,矩阵元素由X和O构成,请求出其中最大的由X构成的蝴蝶形状。
由X构成的蝴蝶形状的定义如下:
存在一个中心点,并且其往左上、左下、右上、右下四个方向扩展相同的长度(扩展的长度上都是X),且左上顶点与左下顶点、右上顶点与右下顶点之间的格子全由X填充。我们不在意在蝴蝶形状内部是X还是O。
例如:
    XOOOX
    XXOXX
    XOXOX
    XXOXX
    XOOOX
是一个X构成的蝴蝶形状。
    X
也是。

    XOOX
    OXXO
    OXXO
    XOXX
不是(不存在中心点)。


#include <bits/stdc++.h>
using namespace std;
//j <= k <= min(dp[1][i][j],dp[2][i][j]) + j - 1
//Max{k} && min(dp[0][i][k],dp[1][i][k]) - k - 1 >= -j
const int inf = 0x3f3f3f3f;
const int maxn = 2010;
struct SegmentTree
{
    struct node
    {
        int l, r, mx;
    } Tree[maxn * 4];
    void pushup(int rt)
    {
        Tree[rt].mx = max(Tree[rt << 1].mx, Tree[rt << 1 | 1].mx);
    }
    void build(int l, int r, int rt)
    {
        Tree[rt].l = l, Tree[rt].r = r, Tree[rt].mx = -inf;
        if (l == r) return;
        int mid = (l + r) / 2;
        build(l, mid, rt * 2);
        build(mid + 1, r, rt * 2 + 1);
        pushup(rt);
    }
    void update(int pos, int val, int rt)
    {
        if (Tree[rt].l == Tree[rt].r)
        {
            Tree[rt].mx = val;
            return;
        }
        int mid = (Tree[rt].l + Tree[rt].r) / 2;
        if (pos <= mid) update(pos, val, rt * 2);
        else update(pos, val, rt * 2 + 1);
        pushup(rt);
    }
    int query(int L, int R, int v, int rt)
    {
        if(Tree[rt].l == Tree[rt].r) return Tree[rt].l;
        int ret=0;
        if(L<=Tree[rt].l&&Tree[rt].r<=R){
            if(Tree[rt*2+1].mx>=v) ret = query(L, R, v, rt*2+1);
            else if(Tree[rt*2].mx>=v) ret = query(L, R, v, rt*2);
            return ret;
        }
        int mid = (Tree[rt].l+Tree[rt].r)/2;
        if(mid<R&&Tree[rt*2+1].mx>=v) ret = query(L, R, v, rt*2+1);
        if(ret) return ret;
        if(L<=mid&&Tree[rt*2].mx>=v) ret = query(L, R, v, rt*2);
        return ret;
    }
}T1, T2;
char s[maxn][maxn];
int dp[3][maxn][maxn];
 
int main()
{
    int n, m;
    scanf("%d %d", &n,&m);
    for(int i=1; i<=n; i++){
        scanf("%s", s[i]+1);
    }
    for(int i=n; i>=1; i--){
        for(int j=1; j<=m; j++){
            if(s[i][j]!='X') continue;
            dp[0][i][j] = dp[0][i+1][j-1]+1;
            dp[1][i][j] = dp[1][i+1][j]+1;
            dp[2][i][j] = dp[2][i+1][j+1]+1;
        }
    }
    int ans=0;
    for(int i=1; i<=n; i++){
        T1.build(1, m, 1);
        T2.build(1, m, 1);
        for(int k=1; k<=m; k++){
            if(k&1) T1.update(k, min(dp[0][i][k],dp[1][i][k])-k-1,1);
            else T2.update(k, min(dp[0][i][k],dp[1][i][k])-k-1,1);
        }
        for(int j=1; j<=n; j++){
            if(s[i][j]!='X') continue;
            int pos=0, x = min(dp[1][i][j], dp[2][i][j]);
            if(x<=ans) continue;
            if(j&1) pos = T1.query(j, x+j-1, -j, 1);
            else pos = T2.query(j, x+j-1, -j, 1);
            if(pos) ans = max(ans, pos-j+1);
        }
    }
    printf("%d\n", ans);
    return 0;
}

D
给定一张n个点,m条边的带权有向无环图,同时给定起点S和终点T,一共有q个询问,每次询问删掉某个点和所有与它相连的边之后ST的最短路,询问之间互相独立(即删除操作在询问结束之后会立即撤销),如果删了那个点后不存在S到T的最短路,则输出-1。



这题的代码是别的AC代码,实现了题解的意思。

#include <bits/stdc++.h>
using namespace std;
#define ll rt<<1
#define rr rt<<1|1
#define lson l, mid, ll
#define rson mid+1, r, rr
#define PB push_back
 
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pli;
const int N = 1e5 + 5;
const LL INF = 10000000000000000LL;
int n, m, s, t;
int x[N<<1], y[N<<1], z[N<<1], deg[N], f[N];
int id[N], tot;
LL dt[N], ds[N];
LL sum[N<<2], laz[N<<2];
queue<int> q;
vector<pii> edges[N];
inline void pushUp(int rt) {
  sum[rt] = min(sum[ll], sum[rr]);
}
inline void pushDown(int rt) {
  sum[ll] = min(sum[ll], laz[rt]); laz[ll] = min(laz[ll], laz[rt]);
  sum[rr] = min(sum[rr], laz[rt]); laz[rr] = min(laz[rr], laz[rt]);
  laz[rt] = INF;
}
 
void build(int l, int r, int rt) {
  sum[rt] = laz[rt] = INF;
  if (l == r) return ;
  int mid = l+r>>1;
  build(lson);
  build(rson);
  pushUp(rt);
}
 
void update(int L, int R, LL v, int l, int r, int rt) {
  if (L <= l && r <= R) {
    sum[rt] = min(sum[rt], v);
    laz[rt] = min(laz[rt], v);
    return ;
  }
  pushDown(rt);
  int mid = l+r>>1;
  if (L <= mid) update(L, R, v, lson);
  if (mid < R) update(L, R, v, rson);
  pushUp(rt);
}
LL query(int p, int l, int r, int rt) {
  if (l == r) return sum[rt];
  pushDown(rt);
  int mid = l+r>>1;
  if (p <= mid) return query(p, lson);
  else return query(p, rson);
}
int dfs(int u) {
  if (f[u] != -1) return f[u];
  if (u == t) {
    f[u] = 1;
    return 1;
  }
  f[u] = 0;
  for (pii edge: edges[u]) {
    if (dfs(edge.first) == 1) f[u] = 1;
  }
  return f[u];
}
int main() {
  while (~scanf("%d%d%d%d", &n, &m, &s, &t)) {
    for (int i = 1; i <= n; ++i) deg[i] = 0;
    for (int i = 1; i <= n; ++i) edges[i].clear();
    for (int i = 1; i <= n; ++i) f[i] = -1;
    for (int i = 1; i <= n; ++i) ds[i] = INF;
    for (int i = 1; i <= n; ++i) dt[i] = INF;
    for (int i = 1; i <= m; ++i) {
      scanf("%d%d%d", x+i, y+i, z+i);
      edges[x[i]].PB(pii(y[i], z[i]));
    }
    dfs(s);
    for (int i = 1; i <= m; ++i) if (f[x[i]] == 1 && f[y[i]] == 1) {
      ++deg[y[i]];
    }
    while (!q.empty()) q.pop();
    ds[s] = 0;
    for (int i = 1; i <= n; ++i) if (!deg[i] && f[i] == 1) q.push(i);
    tot = 0;
    int u, v, w;
    while (!q.empty()) {
      u = q.front(); q.pop();
      id[u] = ++tot;
      for (pii edge: edges[u]) {
        v = edge.first; w = edge.second;
        if (f[v] != 1) continue;
        ds[v] = min(ds[v], ds[u]+w);
        if (--deg[v] == 0) q.push(v);
      }
    }
    dt[t] = 0;
    for (int i = 1; i <= n; ++i) deg[i] = 0;
    for (int i = 1; i <= n; ++i) edges[i].clear();
    for (int i = 1; i <= m; ++i) if (f[x[i]] == 1 && f[y[i]] == 1) {
      ++deg[x[i]];
      edges[y[i]].PB(pii(x[i], z[i]));
    }
    for (int i = 1; i <= n; ++i) if (!deg[i] && f[i] == 1) q.push(i);
    while (!q.empty()) {
      u = q.front(); q.pop();
      for (pii edge: edges[u]) {
        v = edge.first; w = edge.second;
        if (f[v] != 1) continue;
        dt[v] = min(dt[v], dt[u]+w);
        if (--deg[v] == 0) q.push(v);
      }
    }
    build(1, tot, 1);
    for (int i = 1; i <= m; ++i) if (f[x[i]] == 1 && f[y[i]] == 1) {
      if (id[x[i]]+1 > id[y[i]]-1) continue;
      update(id[x[i]]+1, id[y[i]]-1, ds[x[i]] + dt[y[i]] + z[i], 1, tot, 1);
    }
    scanf("%d", &m);
    while (m--) {
      scanf("%d", &u);
      if (ds[t] == INF) {
        printf("-1\n");
        continue;
      }
      if (f[u] != 1) {
        printf("%lld\n", ds[t]);
        continue;
      }
      LL ret = query(id[u], 1, tot, 1);
      if (ret >= INF) ret = -1;
      printf("%lld\n", ret);
    }
  }
}