2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 L题 非递减权值最大


Let SS be a sequence of integers s_{1}s1, s_{2}s2, ......, s_{n}sn Each integer is is associated with a weight by the following rules:

(1) If is is negative, then its weight is 00.

(2) If is is greater than or equal to 1000010000, then its weight is 55. Furthermore, the real integer value of s_{i}si is s_{i}-10000si10000 . For example, if s_{i}si is 1010110101, then is is reset to 101101 and its weight is 55.

(3) Otherwise, its weight is 11.

A non-decreasing subsequence of SS is a subsequence s_{i1}si1, s_{i2}si2, ......, s_{ik}sik, with i_{1}<i_{2}\ ...\ <i_{k}i1<i2 ... <ik, such that, for all 1 \leq j<k1j<k, we have s_{ij}<s_{ij+1}sij<sij+1.

A heaviest non-decreasing subsequence of SS is a non-decreasing subsequence with the maximum sum of weights.

Write a program that reads a sequence of integers, and outputs the weight of its

heaviest non-decreasing subsequence. For example, given the following sequence:

8080 7575 7373 9393 7373 7373 1010110101 9797 -11 -11 114114 -11 1011310113 118118

The heaviest non-decreasing subsequence of the sequence is <73, 73, 73, 101, 113, 118><73,73,73,101,113,118> with the total weight being 1+1+1+5+5+1 = 141+1+1+5+5+1=14. Therefore, your program should output 1414 in this example.

We guarantee that the length of the sequence does not exceed 2*10^{5}2105

Input Format

A list of integers separated by blanks:s_{1}s1, s_{2}s2,......,s_{n}sn

Output Format

A positive integer that is the weight of the heaviest non-decreasing subsequence.

样例输入

80 75 73 93 73 73 10101 97 -1 -1 114 -1 10113 118

样例输出

14

题目来源

2017 ACM-ICPC 亚洲区(南宁赛区)网络赛



负数不用考虑  直接去掉就可以,  

问非递减序列, 中 权值最大是多少;

刚开始理解错了  用到而是 nlog(n)  算法找的 最长上升子序列,然后找的权值,   

但是这样不能保证权值最大;


一个很巧妙的方法就是:  权值是5     我们可以 拆分成5 个相同的数  使权值为1   这样 所有的权值都是1

就变成找 最长上升子序列了


n^n  超时

 还有一种方法就是 动态规划来做 

第二层 用树状数组来维护 前面的最大值



代码:


#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define FIN      freopen("input.txt","r",stdin)
#define FOUT     freopen("output.txt","w",stdout)
#define S1(n)    scanf("%d",&n)
#define SL1(n)   scanf("%I64d",&n)
#define S2(n,m)  scanf("%d%d",&n,&m)
#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)
#define Pr(n)     printf("%d\n",n)

using namespace std;
typedef long long ll;	

const int INF=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int MOD=1e9+7;
const int mod=1e9+7;
int dir[5][2]={0,1,0,-1,1,0,-1,0};


struct node{
	int x,y;
}a[maxn];
int stacks[maxn];
int main()
{
	int x;
	int k=0;
	while((scanf("%d",&x))!=EOF)
	{
		if(x<10000&&x>=0)	
			a[k].x=x,a[k++].y=1;
		else if(x<0)
			continue;
		else if(x>=10000)
		{
			for(int i=1;i<=5;i++)
				a[k].x=x-10000,a[k++].y=1;
		}
			
	}
	stacks[0]=-1;
	int n=k-1;
	int top=0;
	int temp;
	for (int i = 0; i <=n; i++)
    {
        temp=a[i].x;
        if (temp >= stacks[top])
        {
            stacks[++top] = temp;
        }
        else   
        {
            int low = 1, high = top;
            int mid;
            while(low <= high)
            {
                mid = (low + high) / 2;
                if (temp >= stacks[mid])
                {
                    low = mid + 1;
                }
                else
                {
                    high = mid - 1;
                }
        	}
	         stacks[low] = temp;
        }
    }

 	cout<<top<<endl;

	return 0;
}
/*
75 73 93 73000 10101 97 -1 102 114 -1 10113 118
*/




树状数组 解法:


【代码】:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define FIN      freopen("input.txt","r",stdin)
#define FOUT     freopen("output.txt","w",stdout)
#define S1(n)    scanf("%d",&n)
#define SL1(n)   scanf("%I64d",&n)
#define S2(n,m)  scanf("%d%d",&n,&m)
#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)
#define Pr(n)     printf("%d\n",n)

using namespace std;
typedef long long ll;	
const double PI=acos(-1);
const int INF=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int MAX=50005;
const int MOD=1e9+7;
const int mod=1e9+7;
int dir[5][2]={0,1,0,-1,1,0,-1,0};

ll inv[maxn*2]; 
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);}}
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;}
ll lcm(ll a,ll b){ return b/gcd(a,b)*a;}
ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;}
ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;}
ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;}
ll inv2(ll b){return qpow(b,MOD-2);}


struct math_tree{
	int n;
	int a[MAX],Max[MAX],Min[MAX];
	int tree[MAX]; 
	void init(int N)
	{
		n=N;
		for(int i=0;i<=N;i++)
			Max[i]=-(Min[i]=INF);	
	}
	void update(int k,int num)//单点更新 
	{
		a[k]=num;
		while(k<=n)
		{
			tree[k]+=num;
			Min[k]=Max[k]=a[k];
			int lk=k&(-k);
			for(int i=1;i<lk;i<<=1)
			{
				Max[k]=max(Max[k],Max[k-i]);
				Min[k]=min(Min[k],Min[k-i]);
			}
			k+=k&(-k);// lowbit(k)= k&(-k);
		}
	}
	int Sum(int k)
	{
		int sum=0;
		while(k)
		{
			sum+=tree[k];
			k-=k&-k;
		}
		return sum;
	}
	int Get_Sum(int x,int y)
	{
		return Sum(y)-Sum(x-1);
	}
	int Qmax(int x,int y)//[x,y]区间最大值 
    {  
        int ans=-INF;  
        while(y>=x)  
        {  
            ans=max(a[y], ans);  
            y--;  
            for(;y-(y&-y)>=x;y-=(y&-y))  
                ans=max(Max[y],ans);  
        }  
        return ans;  
    } 
	int Qmin(int x,int y)//[x,y] 区间最小值
	{
		int ans=INF;
		while(y>=x)
		{
			ans=min(a[y],ans);
			y--;
			for(;y-(y&-y)>=x;y-=(y&-y))
				ans=min(ans,Min[y]);
		}
		return ans;
	}
}A;
int a[maxn],b[maxn];
int main()
{
	int x;
	int dp;
	int k=1;
	int top=0;
	while(scanf("%d",&x)!=EOF)
	{
		if(x<0)
			continue;
		else if(x>=10000)
		{
			a[k]=x-10000;
			b[k]=5;
		}
		else 
			a[k]=x,b[k]=1;
		top=max(a[k],top);
		k++;
	}
	int n=k-1;
	math_tree ans;
	ans.init(top);
	for(int i=1;i<=n;i++)
	{
		dp=b[i]+ans.Qmax(1,a[i]);// 前a[i] 最大值 
		ans.update(a[i],dp);// 更新 最大值 
	}
	
	printf("%d\n",ans.Qmax(1,top));
	return 0;
}


123

posted @ 2017-09-24 17:44  Sizaif  阅读(163)  评论(0编辑  收藏  举报