首页 > 其他分享 >20231116

20231116

时间:2023-11-16 22:44:40浏览次数:30  
标签:20231116 cout int cin long dfn define

2023/11/16

先是周三训练补题

k题,赛时队友写的,讨论是用dfn序来判断返祖边,也是学到了怎么来判断有向图中的返祖边

做法:dfs的时候,我们只看一条链上的点,我们正常赋值dfn序。如果这是出现dfn[v]<dfn[u],那么这条边一定是返祖边。然后我们回溯的时候把u点的dfn序赋为1e9。这样代表这个点被访问过,不用访问,且也不会出现下一次dfn[v]<dfn[u]的情况

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define Acode ios::sync_with_stdio(false), cin.tie(0)
#define int long long
int n, m;
const int N = 4e5 + 10;
vector<pair<int, int>> g[N];
int dfn[N];
int tot;
vector<int> ans;
int vis[N];
void dfs(int u)
{
    dfn[u] = ++tot;
    for (auto it : g[u])
    {
        int v = it.first;
        int id = it.second;
        if (!dfn[v])
        {
            ans.push_back(id);
            dfs(v);
        }
        else if (dfn[v] > dfn[u])
        {
            ans.push_back(id);
            continue;
        }
        else if (dfn[v] < dfn[u])
            continue;
    }
    dfn[u] = 1e9;
}

void solve()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        if (u == v)
            continue;
        g[u].push_back({v, i});
    }
    for (int i = 1; i <= n; i++)
    {
        if (!dfn[i])
            dfs(i);
    }
    for (auto x : ans)
    {
        vis[x] = 1;
    }
    cout << "YES\n";
    if (ans.size() >= m / 2)
    {
        cout << ans.size() << endl;
        for (auto x : ans)
        {
            cout << x << " ";
        }
    }
    else
    {
        cout << m - ans.size() << endl;
        for (int i = 1; i <= m; i++)
        {
            if (!vis[i])
                cout << i << " ";
        }
    }
}

signed main()
{
    Acode;
    int T = 1;
    while (T--)
    {
        solve();
    }
    return 0;
}

然后看了题解,发现我们想复杂了,u->v,无非两种情况,u大于v或者v大于u。那么我们对两种情况的边分别建图,那么一定有一张图中的边数会大于一半。(因为题目只要求不出现环就行,其他的都没要求)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define Acode ios::sync_with_stdio(false), cin.tie(0)
#define int long long
int n, m;
const int N = 4e5 + 10;

vector<int> g1;
vector<int> g2;

void solve()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        if (u == v)
            continue;
        if (u > v)
            g1.push_back(i);
        else
            g2.push_back(i);
    }
    if (g1.size() >= m / 2)
    {
        cout << "YES\n";
        cout << g1.size() << endl;
        for (auto x : g1)
        {
            cout << x << " ";
        }
    }
    else if (g2.size() >= m / 2)
    {
        cout << "YES\n";
        cout << g2.size() << endl;
        for (auto x : g2)
        {
            cout << x << " ";
        }
    }
    else
        cout << "NO\n";
}

signed main()
{
    Acode;
    int T = 1;
    while (T--)
    {
        solve();
    }
    return 0;
}

B题,计算几何。

一开始不会算多边形面积,队友一句话在圆里,用1/2absin角度,点醒梦中人,刚好题目给的也是角度。

赛时用dp来写,但是wa2,一直过不去

下午调了两个小时没调出来,还是不知道自己错哪里,人已经开始恶心了

1852A - Ntarsis' Set

题目是好题,两个二分要调20分钟,看来还是没想清楚。

思路:对于一个数,我们每次删数后,它位置会前进多少呢,这取决于它当前所在的位置,已经a数组中有几个数小于它当前的位置。 而且这个答案在值域上是有单调性的,过小我们模拟它走完k轮之后,他的位置会为0,过大位置大于1.因为最后的答案,在最后的数组中是第一位,所以一个数最后的位置大于1说明前面还有数。

走k轮,值域上二分答案,每轮二分的得出这一轮要前进多少位置

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define Acode ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long
const int N = 2e5 + 10;
int a[N];
int n, k;

int query(int x)
{
    int l = 1, r = n;
    while (l <= r)
    {
        int mid = l + r >> 1;
        if (a[mid] <= x)  //找有多少数小于等于这个数字,刚好等于的话就减到零,可以判断
            l = mid + 1;
        else
            r = mid - 1;
    }
    return r;
}

bool check(int mid)
{
    for (int i = 1; i <= k; i++)
    {
        int x = query(mid);
        // cerr << "TTTT" << x << endl;
        mid -= x;
    }
    if (mid >= 1)
        return true;
    else
        return false;
}

void solve()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    if (a[1] != 1)
    {
        cout << 1 << endl;
        return;
    }
    int l = 1, r = 1e15;
    while (l <= r)
    {
        int mid = l + r >> 1;
        if (check(mid))
            r = mid - 1;
        else
            l = mid + 1;
        // cerr << mid << " " << check(mid) << endl;
    }
    cout << l << endl;
}

signed main()
{
    Acode;
    int T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

标签:20231116,cout,int,cin,long,dfn,define
From: https://www.cnblogs.com/chenchen336/p/17837455.html

相关文章

  • 20231116打卡
    早上,我有一门UML和算法与数据结构的上机实验课。这门课程旨在培养我们对软件设计和算法实现的能力。在实验课上,我们运用UML(统一建模语言)来设计和建模软件系统,同时编写代码实现各种经典的算法和数据结构,例如排序和查找算法、链表和树等。通过这些实际操作,我加深了对软件工程理论的......
  • 20231116
    今天是个大晴天,18摄氏度,不知道为什么一堆人穿冬季校服。看来还是说明体锻太少了,大家都虚了。哦,上文和下文没有关系。下文是昨天总结出来的,也是也不是,是上高中后总结出来的。形式主义其实是一群傻逼满脑子都是他们认为的理想化,我觉得这种人脑子相当于是被格式化了。也是,生活中接......