[NOIP simulation 26] solution to a problem

Today's test questions adapted from closing the roll to write ...... so aged problem solution.

A. ***** ***** greed

RT, the topic and people tell us that this question be greedy.

The optimal strategy must be dragged off again when disconnected (though do not know why).

If a sequence to meet the nature of the subject, then there must be $ gcd (a_i-a_ {i-1}, a_ {i + 1} -a_i, ...) $ 1 and not $ a_i, a_ {i + 1 }, ... $ vary. So the difference between two adjacent maintenance of each segment of gcd, encounters an element it does not meet or repeated ans ++. set to write more convenient.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<set>
#include<cmath>
using namespace std;
const int N=100005;
int n,a[N],ans=1;
set<int> b;
int gcd(int x,int y)
{
    if(!y)return x;
    return gcd(y,x%y);
}
int now;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    b.insert(a[1]);
    for(int i=2;i<=n;i++)
    {
        now=gcd(now,abs(a[i]-a[i-1]));
        if(now==1||b.count(a[i]))
        {
            ans++;
            now=0;
            b.clear();b.insert(a[i]);
        }
        else b.insert(a[i]);
    }
    cout<<ans<<endl;
    return 0;
}
View Code

B. ** witness *******

RT, the topic and people we witnessed over $ n ^ 2 $ 500,000.

Did not play offline dfs sequence std solution in direct relationship to the side with have included representatives of every answer to violence dfs statistical inquiry. Note that K = 1 special sentenced to build two-way side.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
int n,m,cnt;
const int N=500005;//change it!
int head[N],nxt[N],to[N],tot,vis[N];
void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
bool dfs(int x,int f,int aim)
{
    if(x==aim)return 1;

    for(int i=head[x];i;i=nxt[i])
    {
        if(to[i]!=f)
            if(dfs(to[i],x,aim))return 1;
    }
    return 0;
}
int main()
{
    n=read();m=read();cnt=n;
    while(m--)
    {
        int opt=read();
        if(!opt)
        {
            int op=read(),K=read(),now=++cnt;
            if(K==1)
            {
                int tmp=read();
                add(now,tmp);add(tmp,now);
            }
            else if(op==0)
            {
                for(int i=1;i<=K;i++)
                    add(now,read());    
            }
            else if(op==1)
            {
                for(int i=1;i<=K;i++)
                    add(read(),now);
            }
        }
        else if(opt==1)
        {
            int x=read(),y=read();


            printf("%d\n",dfs(x,0,y));
        }
    }    
    return 0;
}
View Code

C. ** ****** accumulation

RT, the topic and told us to use the heap.

The equation can be a violent dp cut: $ dp [i] = \ min \ limits _ {j = max (0, iK)} ^ {i-1} dp [j] + max (sum [i] -sum [ j], b [j]) $

For all j, $ dp [j] + b [j] $ and $ dp [j] -sum [j] $ is a predetermined value

So with two stacks, respectively, to maintain both. Required $ dp [i] = min (heap1.top, heap2.top + sum [i]) $

First, check the first stack, if j is smaller than the withdrawn iK, pop continue to take off. If withdrawn than $ dp [j] -sum [j] + sum [i] $ small, add it to the second pile, pop off.

So take up to legal, the second stack is the same.

Time complexity $ O (nlogn) $

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
#define pa pair<ll,int>
int n,K;
const int N=500005;
int a[N],b[N];
ll sum[N],dp[N];
priority_queue<pa,vector<pa>,greater<pa> >q1,q2;
int main()
{
    scanf("%d%d",&n,&K);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),sum[i]=sum[i-1]+1LL*a[i];
    for(int i=0;i<n;i++)
        scanf("%d",&b[i]);
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    q1.push(make_pair(dp[0]+1LL*b[0],0));
    for(int i=1;i<=n;i++)
    {
        ll val1=0x7ffffffffff,val2=0x7ffffffffff;
        while(!q1.empty())
        {
            ll val=q1.top().first;int id=q1.top().second;
            if(id<i-K)
            {
                q1.pop();continue;
            }
            if(val<dp[id]-sum[id]+sum[i])
            {
                q2.push(make_pair(dp[id]-sum[id],id));q1.pop();
                continue;
            }
            val1=min(val1,val);
            break;
            
        }

        while(!q2.empty())
        {
            ll val=q2.top().first;
            int id=q2.top().second;
            if(id<i-K)
            {
                q2.pop();continue;
            }
            val2=min(val2,val);
            break;


        }
        dp[i]=min(val1,val2+sum[i]);
        //cout<<i<<' '<<dp[i]<<endl;
        q1.push(make_pair(dp[i]+b[i],i));
    }
    cout<<dp[n]<<endl;
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Rorschach-XR/p/11391241.html