• 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
  • 相关阅读:
    云开发数据库 Firebase Firestore 零基础入门视频实战教程(7 个视频)
    在 2021 年你需要掌握的 7 种关于 JavaScript 的数组方法
    2021 年写 JavaScript 代码的 17 个优化技巧
    Redis 学习笔记系列文章之 Redis 的安装与配置 (一)
    selenium webdriver 删除元素
    FFT板子
    pytest一:运行几个简单的测试用例终端显示的信息
    JS 日期取年月日
    将博客搬至CSDN
    c语言编译器
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9832331.html
Copyright © 2020-2023  润新知