1. 程式人生 > >2017 icpc 瀋陽網路賽

2017 icpc 瀋陽網路賽

題目:連結

B cable cable cable:

觀察得,答案為K*(M-K+1)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    ll M,K;
    while(~scanf("%lld%lld",&M,&K))
        printf("%lld\n",K*(M-K+1));
    return 0;
}

D array array array:

若最長上升子序列的長度大於等於n-k,則是可以的,因為這裡要求的不是嚴格的遞增,

所以可以先將原陣列處理成沒有相同數字的陣列,然後處理就好了。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,k,dp[maxn],a[maxn];
vector<int>G[maxn];
bool check()
{
    for(int i=0;i<maxn;i++) dp[i]=2e9;
    for(int i=0;i<n;i++) *lower_bound(dp,dp+n,a[i])=a[i];
    int len=lower_bound(dp,dp+n,2e9)-dp;
    return n-len<=k;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        for(int i=0;i<maxn;i++) G[i].clear();
        scanf("%d%d",&n,&k);
        for(int i=0;i<n;i++)
        {
            int x;scanf("%d",&x);
            G[x].push_back(i);
        }
        int tol=0;
        for(int i=1;i<maxn;i++)
        {
            int len=G[i].size();
            for(int j=0;j<len;j++)
            {
                a[G[i][j]]=++tol;
            }
        }
        int ans=check();
        tol=0;
        for(int i=1;i<maxn;i++)
        {
            int len=G[i].size();
            for(int j=len-1;j>=0;j--)
            {
                a[G[i][j]]=++tol;
            }
        }
        ans|=check();
        if(ans) printf("A is a magic array.\n");
        else printf("A is not a magic array.\n");
    }
    return 0;
}

E number number number:

手推幾項發現是斐波那契數列的第2*(k+1)項,直接矩陣快速冪即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=998244353;
struct node
{
    ll t[2][2];
}a,b;
node cheng(node &x,node &y)
{
    node r;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            r.t[i][j]=0;
            for(int k=0;k<2;k++)
                (r.t[i][j]+=x.t[i][k]*y.t[k][j])%=mod;
        }
    }
    return r;
}
void pow1(int k)
{
    while(k)
    {
        if(k&1) a=cheng(a,b);
        b=cheng(b,b);
        k/=2;
    }
}
int main()
{
    int k;
    while(~scanf("%d",&k))
    {
        a.t[0][0]=1,a.t[0][1]=0;
        a.t[1][0]=0,a.t[1][1]=0;
        b.t[0][0]=1,b.t[0][1]=1;
        b.t[1][0]=1,b.t[1][1]=0;
        pow1(2*(k+1));
        printf("%lld\n",(a.t[0][0]-1+mod)%mod);
    }
    return 0;
}

H transaction transaction transaction:

裸的樹分治:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node
{
    int to,cost,next;
}rode[maxn*2];
int val[maxn],n,tol,head[maxn];
int son[maxn],root,now_size;
bool vis[maxn];
int ans,cnt1,cnt2;
void add_edge(int a,int b,int c)
{
    rode[tol].to=b;
    rode[tol].cost=c;
    rode[tol].next=head[a];
    head[a]=tol++;
}
void get_root(int v,int fa,int SIZE)
{
    son[v]=1;
    int ma=0;
    for(int i=head[v];i!=-1;i=rode[i].next)
    {
        node &e=rode[i];
        if(e.to==fa||vis[e.to]) continue;
        get_root(e.to,v,SIZE);
        son[v]+=son[e.to];
        ma=max(ma,son[e.to]);
    }
    ma=max(ma,SIZE-son[v]);
    if(ma<now_size)
    {
        now_size=ma;
        root=v;
    }
}
void cal(int v,int fa,int par,int dist)
{
    for(int i=head[v];i!=-1;i=rode[i].next)
    {
        node &e=rode[i];
        if(e.to==fa||vis[e.to]) continue;
        if(val[e.to]-val[par]-dist-e.cost>cnt1) cnt1=val[e.to]-val[par]-dist-e.cost;
        if(val[par]-val[e.to]-dist-e.cost>cnt2) cnt2=val[par]-val[e.to]-dist-e.cost;
        ans=max(ans,cnt1+cnt2);
        cal(e.to,v,par,dist+e.cost);
    }
}
void dfs(int v)
{
    vis[v]=1;
    cnt1=0,cnt2=0;
    cal(v,0,v,0);
    for(int i=head[v];i!=-1;i=rode[i].next)
    {
        node &e=rode[i];
        if(vis[e.to]) continue;
        get_root(root=e.to,v,now_size=son[e.to]);
        dfs(root);
    }
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
        tol=0;ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&val[i]);
        for(int i=1;i<n;i++)
        {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            add_edge(x,y,z);add_edge(y,x,z);
        }
        get_root(root=1,0,now_size=n);
        dfs(root);
        printf("%d\n",ans);
    }
    return 0;
}

L card card card:

sum[i]為前i項值得字首和,若1~i之間所有的sum[i]都>=0,則滿足條件。

拓展即i~j中所有的sum[k]都滿足sum[k]>=sum[i-1],只要令j-i+1==n即可滿足題意。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+10;
int deq[maxn],a[maxn],b[maxn],sum[maxn];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) scanf("%d",&b[i]);
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]-b[i];
        for(int i=1;i<=n;i++) sum[i+n]=sum[i+n-1]+a[i]-b[i];
        int id=0;
        for(int i=1;i<=2*n;i++)
        {
            while(sum[i]<sum[id]) id++;
            if(i-id==n)
            {
                printf("%d\n",id);
                break;
            }
        }
    }
    return 0;
}