集训DAY1 机房测试(贪心,图论)

这里写图片描述

这里写图片描述
解题报告:
贪心大水题
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int a[100010];
int n ,i,ans=0,now=0;

int main()
{
    freopen("grace.in","r",stdin);
    freopen("grace.out","w",stdout);
    scanf("%d",&n);
    for(i=1;i<=n;++i) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for(i=1;i<=n;++i)
    {
        if(a[i]==a[i-1]) now++;
        else now=1;
        ans=max(ans,now);
    }
    printf("%d\n",n-ans);
    return 0;
}

这里写图片描述
解题报告:
单独处理
代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
#define mod 23333333333333333ll
using namespace std;
long long m;
long long pc(long long x,long long y)
{
    x=x%mod,y=y%mod;
    long long ans=0;
    while(y)
    {
        if(y&1) ans=(ans+x)%mod;
        x=(x+x)%mod,y>>=1;
    }
    return ans;
}
long long calc(long long n)
{
    if(n<0) return 0;
    long long i,ans=pc((n&1)?n:(n>>1),(n&1)?((n>>1)+1):(n+1)),sum;
    for(i=1ll<<62;i;i>>=1)
    {
        if(m&i)
        {
            sum=(n/i/2)*i;
            if(n&i) sum+=n%i+1;
            ans=(ans+pc(n+1-sum*2,i))%mod;
        }
    }
    return ans;
}
int main()
{
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    long long T,a,b;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld%lld%lld",&a,&b,&m);
        printf("%lld\n",(calc(b)-calc(a-1)+mod)%mod);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

这里写图片描述

这里写图片描述
解题报告:
缩点之后LCA
代码如下:

#include <cstdio>
#include <algorithm>
#define N 200010
using namespace std;
int head[N][2] , to[N][2] , next1[N][2] , cnt[2] , dd[N] , low[N] , tot , vis[N] , ins[N] , sta[N] , top , bel[N] , num;
int fa[N][22] , deep[N] , sum[N][22] , log1[N] , pow1[N];
void add(int p , int x , int y)
{
    to[++cnt[p]][p] = y , next1[cnt[p]][p] = head[x][p] , head[x][p] = cnt[p];
}
void tarjan(int x , int from)
{
    int i , t;
    dd[x] = low[x] = ++tot , vis[x] = ins[x] = 1 , sta[++top] = x;
    for(i = head[x][0] ; i ; i = next1[i][0])
    {
        if(to[i][0] == from) continue;
        if(!vis[to[i][0]]) tarjan(to[i][0] , x) , low[x] = min(low[x] , low[to[i][0]]);
        else if(ins[to[i][0]]) low[x] = min(low[x] , dd[to[i][0]]);
    }
    if(dd[x] == low[x])
    {
        num ++ ;
        do
        {
            t = sta[top -- ] , ins[t] = 0 , bel[t] = num;
            if(t != x) sum[num][0] = 1;
        }while(t != x);
    }
}
void dfs(int x)
{
    int i;
    for(i = 1 ; i <= log1[deep[x]] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1] , sum[x][i] = sum[x][i - 1] + sum[fa[x][i - 1]][i - 1];
    for(i = head[x][1] ; i ; i = next1[i][1]) if(to[i][1] != fa[x][0]) fa[to[i][1]][0] = x , deep[to[i][1]] = deep[x] + 1 , dfs(to[i][1]);
}
int cal(int x , int y)
{
    int i , ans = 0;
    if(deep[x] < deep[y]) swap(x , y);
    for(i = log1[deep[x] - deep[y]] ; i >= 0 ; i -- ) if(deep[x] - deep[y] >= (1 << i)) ans += sum[x][i] , x = fa[x][i];
    for(i = log1[deep[x]] ; i >= 0 ; i -- ) if(fa[x][i] != fa[y][i]) ans += sum[x][i] + sum[y][i] , x = fa[x][i] , y = fa[y][i];
    if(x != y) ans += sum[x][0] + sum[y][0] , x = fa[x][0];
    return ans + sum[x][0];
}
int main()
{
    freopen("cactus.in","r",stdin);
    freopen("cactus.out","w",stdout);
    int n , m , k , i , x , y;
    scanf("%d%d" , &n , &m);
    while(m -- ) scanf("%d%d" , &x , &y) , add(0 , x , y) , add(0 , y , x);
    tarjan(1 , 0);
    for(x = 1 ; x <= n ; x ++ ) for(i = head[x][0] ; i ; i = next1[i][0]) if(bel[x] != bel[to[i][0]]) add(1 , bel[x] , bel[to[i][0]]);
    pow1[0] = 1 , pow1[1] = 2;
    for(i = 2 ; i <= n ; i ++ ) log1[i] = log1[i >> 1] + 1 , pow1[i] = pow1[i - 1] * 2 % 1000000007;
    dfs(1);
    scanf("%d" , &k);
    while(k -- ) scanf("%d%d" , &x , &y) , printf("%d\n" , pow1[cal(bel[x] , bel[y])]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

这里写图片描述

这里写图片描述
解题报告:
贪心
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010

int n,m;
long long ans=0;

int main()
{
    freopen("flow.in","r",stdin);
    freopen("flow.out","w",stdout);
    scanf("%d%d",&n,&m);
    int pos;
    for(int i=1;i<=n;++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(i==1) {pos=x;continue;}
        if(x>y) {int t=x,x=y,y=t;}
        if(pos<x) {ans+=x-pos;pos=x;}
        if(pos>y) {ans+=pos-y;pos=y;}
    }
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值