首页 > 其他分享 >UNR#3 Day1

UNR#3 Day1

时间:2024-05-29 13:46:38浏览次数:20  
标签:UNR return cin int ll pos Day1 const

A. 鸽子固定器

把固定器按 \(s\) 排序。

如果选的个数 \(< m\),选出来的一定是一个连续段,否则再多选夹在中间的固定器一定优。

如果选的个数 \(= m\),按牢固度从小到大考虑每一个固定器,找以当前固定器为最小牢固度的长度为 \(m\) 的最优序列,分讨几种情况之后不难发现忽略牢固度更小的固定器后,这还是个连续段。

想清楚了暴力做就好,时间复杂度 \(\mathcal O(nm)\)。

注意别用 vector,它的 erase 的时间复杂度是 \(\mathcal O(n)\)。

推荐手写链表。

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

constexpr int N = 2e5 + 10;

int n, m, ds, dv, pre[N], lat[N];

struct Node {int s, v, id;} a[N], b[N], c[N];
bool cmps(const Node &lhs, const Node &rhs) {return lhs.s < rhs.s;}
bool cmpv(const Node &lhs, const Node &rhs) {return lhs.v < rhs.v;}

inline void chkmax(ll &x, ll y) {x = max(x, y);}
inline ll S(ll x) {return ds == 1 ? x : x * x;}
inline ll V(ll x) {return dv == 1 ? x : x * x;}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
    cin >> n >> m >> ds >> dv;
    for (int i = 1; i <= n; i++) cin >> a[i].s >> a[i].v;
    sort(a + 1, a + n + 1, cmps);
    ll ans = 0;
    for (int len = 1; len < m; len++) {
        int sv = 0;
        for (int i = 1; i <= len; i++) sv += a[i].v;
        for (int i = len + 1; chkmax(ans, V(sv) - S(a[i - 1].s - a[i - len].s)), i <= n; sv += a[i].v - a[i - len].v, i++);
    }
    for (int i = 1; i <= n; i++) a[i].id = i, b[i] = a[i], pre[i] = i - 1, lat[i] = i + 1;
    sort(b + 1, b + n + 1, cmpv);
    for (int j = 1; j <= n - m + 1; j++) {
        int p = b[j].id, tot = 0;
        for (int i = 2, cur = pre[p]; i <= m && cur; i++, cur = pre[cur]) c[++tot] = a[cur];
        reverse(c + 1, c + tot + 1);
        for (int i = 1, cur = p; i <= m && cur <= n; i++, cur = lat[cur]) c[++tot] = a[cur];
        int sv = 0;
        for (int i = 1; i <= m; i++) sv += c[i].v;
        for (int i = m + 1; chkmax(ans, V(sv) - S(c[i - 1].s - c[i - m].s)), i <= tot; sv += c[i].v - c[i - m].v, i++);
        pre[lat[p]] = pre[p], lat[pre[p]] = lat[p];
    }
    cout << ans;
    return 0;
}

B. To Do Tree

考虑没有 \(m\) 的限制时怎么做,显然直接拓扑排序即可。

现在有了 \(m\) 的限制,贪心地选子树大的,然后全对了。

证明不会。

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

constexpr int N = 1e5 + 10;

int n, m, fa[N], sz[N];

vector<int> G[N];

struct cmp {const bool operator()(const int &lhs, const int &rhs) {return sz[lhs] < sz[rhs];}};
priority_queue<int, vector<int>, cmp> q;

void dfs(int u) {
    sz[u] = 1;
    for (int v : G[u]) dfs(v), sz[u] += sz[v];
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
    cin >> n >> m;
    for (int i = 2; i <= n; i++) cin >> fa[i], G[fa[i]].emplace_back(i);
    dfs(1);

    vector<vector<int>> ans;
    vector<int> op;

    q.emplace(1);
    while (!q.empty()) {
        op.clear();
        for (int i = 1; i <= m && !q.empty(); i++) {op.emplace_back(q.top()); q.pop();}
        ans.emplace_back(op);
        for (int u : op) for (int v : G[u]) q.emplace(v);
    }

    cout << ans.size();
    for (auto i : ans) {
        cout << '\n' << i.size();
        for (int j : i) cout << ' ' << j;
    }
    return 0;
}

C. 配对树

考虑这样一种情况,\(x, y\) 都在以 \(u\) 为根的子树上,但他们没有配对,实际上的配对情况是 \((x, x'), (y, y')\),此时把配对改为 \((x, y), (x', y')\) 一定不劣。

所以一定存在一个最优匹配,使得所有路径不交。

考虑每条边对答案的贡献。

边 \((fa_u, u)\) 会被记入答案当且仅当以 \(u\) 为根的子树内 ddl 数量为奇数。

我们把 \(u\) 子树内的 ddl 视作 \(1\),其余的视作 \(0\),对于一个固定的 \(u\),我们需要知道这个 \(01\) 序列里 \(1\) 的个数是奇数的子区间数。

对 \(01\) 序列做前缀和得到 \(s\),所求即 \(s_r - s_{l - 1} \equiv 1 \pmod2, l - 1 \equiv r \pmod2\) 的 \((l, r)\) 的个数,分下标和值的奇偶四种情况讨论就好。

时间复杂度 \(\mathcal O(n^2 + nm)\)。

用线段树合并维护 \(s\),时间复杂度 \(\mathcal O(n + m \log m)\)。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

constexpr int N = 1e5 + 10, TN = N * 40, MOD = 998244353;

int n, m, rt[N], ans;

int tot, head[N];
struct Edge {int to, nxt, val;} e[N << 1];
inline void add(int u, int v, int w) {e[++tot] = Edge{v, head[u], w}, head[u] = tot;}

namespace SGT {
    #define lson t[pos].ls
    #define rson t[pos].rs

    int tot;
    struct Seg {int c[2][2], ls, rs; bool s;} t[TN];

    inline void pu(int pos, int l, int r) {
        int mid = (l + r) >> 1;
        for (int i : {0, 1}) for (int j : {0, 1}) {
            t[pos].c[i][j] = 0;
            if (lson) t[pos].c[i][j] += t[lson].c[i][j];
            else if (!j) t[pos].c[i][j] += ((mid + 2 + i) >> 1) - ((l + 1 + i) >> 1); 
            if (rson) t[pos].c[i][j] += t[rson].c[i][j ^ t[lson].s];
            else if (j == t[lson].s) t[pos].c[i][j] += ((r + i) >> 1) - ((mid + i) >> 1);
        }
        t[pos].s = t[lson].s ^ t[rson].s;
    }

    void upd(int &pos, int l, int r, int x) {
        if (!pos) pos = ++tot;
        if (l == r) {t[pos].s = 1, t[pos].c[l & 1][1] = 1; return;}
        int mid = (l + r) >> 1;
        x <= mid ? upd(lson, l, mid, x) : upd(rson, mid + 1, r, x);
        pu(pos, l, r);
    }

    int merge(int x, int y, int l, int r) {
        if (!x || !y) return x ^ y;
        int mid = (l + r) >> 1;
        t[x].ls = merge(t[x].ls, t[y].ls, l, mid), t[x].rs = merge(t[x].rs, t[y].rs, mid + 1, r);
        pu(x, l, r); return x;
    }

    inline ll query(int pos) {return (1ll * t[pos].c[0][1] * t[pos].c[0][0] + 1ll * t[pos].c[1][0] * t[pos].c[1][1]) % MOD;}
}

void dfs(int u, int fa) {
    for (int i = head[u], v; v = e[i].to, i; i = e[i].nxt) if (v != fa) {
        dfs(v, u);
        ans = (ans + SGT::query(rt[v]) * e[i].val) % MOD;
        rt[u] = SGT::merge(rt[u], rt[v], 0, m);
    }
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
    cin >> n >> m;
    for (int i = 1, u, v, w; i < n; i++) cin >> u >> v >> w, add(u, v, w), add(v, u, w);
    for (int i = 1, x; i <= m; i++) cin >> x, SGT::upd(rt[x], 0, m, i);
    dfs(1, -1);
    cout << ans;
    return 0;
}

标签:UNR,return,cin,int,ll,pos,Day1,const
From: https://www.cnblogs.com/chy12321/p/18220080

相关文章

  • Vue从入门到实战Day12~14 - Vue3大事件管理系统
    一、用到的知识Vue3compositionAPIPinia/Pinia持久化处理ElementPlus(表单校验,表格处理,组件封装)pnpm包管理升级Eslint+prettier更规范的配置husky(Githooks工具):代码提交之前,进行校验请求模块设计VueRouter4路由设计AI大模型开发一整个项目模块(掌握最新的开发方式)·......
  • Cesium4Unreal - # 002 线图元绘制
    文章目录基础点绘制1思路2步骤2.1创建一个自定义组件2.2重写CreateSceneProxy方法2.3实现自定义的场景代理类2.4在场景代理类中实现绘制逻辑2.5使用自定义组件3代码实现3.1c++代码3.1.1自定义组件代码MyPrimitivePointComponent.hMyPri......
  • Day19学习Java
    什么是注解java.annotation包Annotation是从JDK1.5开始引入的新技术,注解即可以对程序员解释又可以对程序解释注解与注释的区别注释:对程序员解释代码信息注解:对程序和程序员解释代码信息注解的所用不是程序本身,可以对程序作出解释(与注释(comment)类似)可以被其他程序......
  • [Day1]跟随狂神说学Java(1)
    MarkDown语法的使用标题的使用'#'+空格为一级标题'##'+空格为二级标题......以此类推最多六级标题字体粗体内容前后使用两个‘*’斜体内容前后使用一个‘*’粗斜体内容前后使用三个‘*’横线内容前后使用两个‘~’引用遇见王某说使用'>'来使用分割线分别......
  • 持续性学习-Day16(前端基础JavaScript)
    LearnJavaScript参考教学视频:秦疆参考知识UI框架Ant-design:阿里巴巴出品,基于React的UI框架ElementUI、iview、ice:饿了吗出品,基于VUE的UI框架BootStrap:Twitter推出的一个用于前端开发的开源工具包AmazeUI:一款HTML5跨屏前端框架JavaScript构建工具Babel:JS编译......
  • Day1_QT界面设计
    1、创建登录界面2、创建注册界面3、实现需求:启动程序主界面优先显式登录界面,点击注册后跳转到注册界面点击注册按钮,就会发出一个信号,这个信号由switchRegister来接收,该信号发送给mainWindow来切换界面connect(ui->reg_btn,&QPushButton::clicked,this,&LoginDialog::sw......
  • day10今日笔记
    今日笔记grepgrep是对数据进行过滤查找关键字源数据可以是文件内容grephello/opt/hello.txt,找出存在hello的那一行命令的执行结果,这个需要结合管道符使用,cat/etc/passwd|grep'root'测试数据Iteachlinux.Ilikepython.Myqqis877348180.Mynameis......
  • day13——常用API&日期类
    day13——常用API&日期类一、StringBuilder类StringBuilder代表可变字符串对象,相当于是一个容器,它里面的字符串是可以改变的,就是用来操作字符串的。好处:StringBuilder比String更合适做字符串的修改操作,效率更高,代码也更加简洁。1.1StringBuilder方法演示接下来我们用......
  • day14--Lambda、方法引用、算法、正则表达式、数据结构
    day14–Lambda、方法引用、算法、正则表达式、数据结构一、Arrays类接下来我们学习的类叫做Arrays,其实Arrays并不是重点,但是我们通过Arrays这个类的学习有助于我们理解下一个知识点Lambda的学习。所以我们这里先学习Arrays,再通过Arrays来学习Lamdba这样学习会更丝滑一些_.......
  • LOJ#4149. 「JOISC 2024 Day1」滑雪 2
    首先,不存在\(H_i<H_j\)时增高\(H_i\)至\(H_j+1\)后连\(i\toj\)更优,因为增高后原来能连\(i\)的点现在不一定能连\(i\)了,原来能连\(j\)的点还是能连\(j\),此时的方案集必然是原方案集的子集,答案一定不会更优,又因为你付出了增高的费用,所以这样一定劣。那么我们......