noip模拟赛

T1 

给一个01矩阵,求一个最大子矩阵,矩阵内的和不超过k

$k leq n^2$

$n leq 500$

sol:$O(n^4)$枚举左上角和右下角,发现后两维有单调性,可以用一个滑窗来搞

但其实非常优秀的枚举3个坐标然后二分第四个坐标的$O(n^3logn)$做法是能过的...本地1.3s

T2

给n个点的坐标和势力范围,每个点向势力范围内每个点连长度为$t_i$的边,求最短路

$n leq 150000$

sol:线段树优化建图!感觉自己押到题了 qwq

线段树上从上往下连长度为$0$的边,每个点向区间连边,直接最短路即可

T3

一棵树,第$i$个点可以花$a_i$的代价变成关键点,定义这个树的代价为建立关键点的代价 + 非关键点到他最近的关键点距离之和

求最小代价

$n leq 2500$

sol:

有点难

先考虑30分的brute force($n leq 10$)

枚举全排列即可

然后我们考虑另外40分的dp(树是一条链)

我们的状态是dp[i]表示最后一个关键点建在$i$的最小代价

转移的时候枚举下一个关键点建在哪,可以发现这两个点之间的所有点,坐标小于等于$avg$(这两个关键点的平均值)的往左走,剩下的往右走

这样就可以转移了

需要注意的是,如果没有建过关键点,代价就是这个点建关键点的代价 + 1~i全走到它的代价

正解非常的CF

我们考虑放宽限制,用$f_{(i,j)}$表示$i$的子树里,钦定所有点走到$j$的最小代价

$g[i]$表示$i$子树的最小代价

为什么这样是对的呢,我们可以想一下,最小的答案里,所有点必然不会绕路走到一个比较远的点

转移就考虑子树里的点是走到$j$还是“另起炉灶”自己搞一个关键点出来

$f_{(i,j)} = a_j + dis(i,j) + sum (MINg[to],f_{(to,j)} - a_j)$

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
int n,k;
int a[510][510],s[510][510];
inline int check(int stx,int sty,int edx,int edy)
{
    return (s[edx][edy] - s[stx - 1][edy] - s[edx][sty - 1] + s[stx - 1][sty - 1] <= k);
}
int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    int ans = 0;
    n = read(),k = read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)a[i][j] = read();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)s[i][j] = a[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int t=i,tmp,st=n;t<=n;t++)
            {
                tmp=s[t][st]-s[i-1][st]-s[t][j-1]+s[i-1][j-1];
                while(tmp>k&&st>j) st--,tmp=s[t][st]-s[i-1][st]-s[t][j-1]+s[i-1][j-1];
                ans=max(ans,(t-i+1)*(st-j+1));
            }
    cout<<ans;
}
T1
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
typedef long long ll;
const int maxn=2610;
int n,cost[maxn],first[maxn],nxt[maxn<<1],to[maxn<<1],dis[maxn<<1],e;
void AddEdge(int u,int v,int w) {
    to[++e]=v;dis[e]=w;nxt[e]=first[u];first[u]=e;
    to[++e]=u;dis[e]=w;nxt[e]=first[v];first[v]=e;
}
int dist[maxn][maxn];
void dfs(int x,int fa,int s) {
    for(int i=first[x];i;i=nxt[i]) if(to[i]!=fa) dist[s][to[i]]=dist[s][x]+dis[i],dfs(to[i],x,s);
}
int f[maxn][maxn],g[maxn];
void dp(int x,int fa) {
    for(int i=first[x];i;i=nxt[i]) if(to[i]!=fa) dp(to[i],x);
    rep(j,1,n) {
        f[x][j]=cost[j]+dist[x][j];
        for(int i=first[x];i;i=nxt[i]) if(to[i]!=fa) f[x][j]+=min(g[to[i]],f[to[i]][j]-cost[j]);
    }
    g[x]=f[x][1];
    rep(i,2,n) g[x]=min(g[x],f[x][i]);
}
int main() {
    freopen("design.in","r",stdin);
    freopen("design.out","w",stdout);
    n=read();
    rep(i,1,n) cost[i]=read();
    rep(i,1,n-1) {
        int u=read(),v=read(),w=read();
        AddEdge(u,v,w);
    } 
    rep(i,1,n) dfs(i,0,i);
    dp(1,0);
    printf("%d
",g[1]);
    return 0;
}
T2
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
    return x * f;
}
const int maxn = 160000;
int n,S,T;
int x[maxn],w[maxn],t[maxn];
int first[maxn * 20],to[maxn * 30],nx[maxn * 30],val[maxn * 30],cnt;
inline void add(int u,int v,int w)
{
    to[++cnt] = v;
    nx[cnt] = first[u];
    first[u] = cnt;
    val[cnt] = w;
}
#define ls (x << 1)
#define rs ((x << 1) | 1)
int lb[maxn],rb[maxn];
inline int getpos(int x){return 1+ n + x;}
inline void build(int x,int l,int r)
{
    if(l == r)
    {
        add(getpos(x),l,0);
        return;
    }
    int mid = (l + r) >> 1;
    build(ls,l,mid);build(rs,mid + 1,r);
    add(getpos(x),getpos(ls),0);
    add(getpos(x),getpos(rs),0);
}
int get_left(int pos)
{
    int l = 1,r = pos,mid,ans = r;
    while(l <= r)
    {
        mid = (l + r) >> 1;
        if(x[pos] - w[pos] <= x[mid])ans = mid,r = mid - 1;
        else l = mid + 1;
    }
    return ans;
}
int get_right(int pos)
{
    int l = pos,r = n,mid,ans = l;
    while(l <= r)
    {
        mid = (l + r) >> 1;
        if(x[pos] + w[pos] >= x[mid])ans = mid,l = mid + 1;
        else r = mid - 1;
    }
    return ans;
}
inline void update(int x,int l,int r,int L,int R,int np,int nv)
{
    if(L <= l && r <= R)
    {
        add(np,getpos(x),nv);
        //cout<<np<<" "<<getpos(x)<<" "<<nv<<endl;
        return;
    }
    int mid = (l + r) >> 1;
    if(L <= mid)update(ls,l,mid,L,R,np,nv);
    if(R > mid)update(rs,mid + 1,r,L,R,np,nv); 
}
#define pa pair<LL,int>
priority_queue<pa,vector<pa>,greater<pa> > q;
LL dis[maxn << 4];
int vis[maxn << 4];
inline void dij()
{
    q.push(make_pair(0LL,S));
    memset(dis,63,sizeof(dis));dis[S] = 0;
    while(!q.empty())
    {
        int now = q.top().second;q.pop();
        //cout<<now<<" "<<dis[now]<<endl;
        if(vis[now])continue;
        vis[now] = 1;
        for(int i=first[now];i;i=nx[i])
        {
            if(dis[to[i]] > dis[now] + val[i])
            {
                dis[to[i]] = dis[now] + val[i];
                q.push(make_pair(dis[to[i]],to[i]));
            }
        }
    }
}
int main()
{
    freopen("trip.in","r",stdin);
    freopen("trip.out","w",stdout);
    n = read(),S = read(),T = read();
    for(int i=1;i<=n;i++)x[i] = read();
    for(int i=1;i<=n;i++)w[i] = read();
    for(int i=1;i<=n;i++)t[i] = read();
    for(int i=1;i<=n;i++)
    {
        lb[i] = get_left(i);
        rb[i] = get_right(i);
        //cout<<lb[i]<<" "<<rb[i]<<endl;
    }
    build(1,1,n);
    for(int i=1;i<=n;i++)update(1,1,n,lb[i],rb[i],i,t[i]);
    dij();
    cout<<dis[T];
}

/*
7 3 7
-1 0 1 2 3 5 10
11 0 1 1 4 10 2
3 1 1 1 2 4 5
*/
T3
原文地址:https://www.cnblogs.com/Kong-Ruo/p/9832331.html