您的位置:首页 > 其它

FZU2236 第十四个目标 (树状数组+离散化)

2018-01-29 16:37 381 查看
题目传送门:点击打开链接


 Problem H 第十四个目标

Accept: 44    Submit: 170

Time Limit: 1000 mSec    Memory Limit : 32768 KB



 Problem Description

目暮警官、妃英里、阿笠博士等人接连遭到不明身份之人的暗算,柯南追踪伤害阿笠博士的凶手,根据几起案件现场留下的线索发现凶手按照扑克牌的顺序行凶。在经过一系列的推理后,柯南发现受害者的名字均包含扑克牌的数值,且扑克牌的大小是严格递增的,此外遇害者与毛利小五郎有关。

为了避免下一个遇害者的出现,柯南将可能遭到暗算的人中的数字按关联程度排列了出来,即顺序不可改变。柯南需要知道共有多少种可能结果,满足受害人名字出现的数字严格递增,但是他柯南要找出关键的证据所在,所以这个任务就交给你了。

(如果你看不懂上面在说什么,这题是求一个数列中严格递增子序列的个数。比如数列(1,3,2)的严格递增子序列有(1)、(3)、(2)、(1,3)、(1,2),共5个。长得一样的但是位置不同的算不同的子序列,比如数列(3,3)的答案是2。)



 Input

多组数据(<=10),处理到EOF。

第一行输入正整数N(N≤100 000),表示共有N个人。

第二行共有N个整数Ai(1≤Ai≤10^9),表示第i个人名字中的数字。



 Output

每组数据输出一个整数,表示所有可能的结果。由于结果可能较大,对1 000 000 007取模后输出。



 Sample Input

31 3 2



 Sample Output

5



 Source

2016福州大学第十三届程序设计竞赛
好题一枚,了解了离散化。

题意是求出每个i值对应的可以到达的严格递增子序列,然后从n往下来加一个和就好了。n就代表了前边所有的结果的和。

因为每一种都情况都用树状数组到了n。

所以离散化 然后树状数组

#include<stdio.h>
#include<iostream>
#include <algorithm>
#include<string.h>
#include<vector>
#include<math.h>
#include<queue>
#include<deque>
#include<map>
#include<set>
#define ll long long
#define INF 0x3f3f3f3f
const int mod = 1e9+7;
using namespace std;
int KGCD(int a,int b){if(a==0)return b;if(b==0)return a;if(~a&1){ if(b&1) return KGCD(a>>1,b);else return KGCD(a>>1,b>>1) <<1; } if(~b & 1) return KGCD(a, b>>1); if(a > b) return KGCD((a-b)>>1, b);return KGCD((b-a)>>1, a);}
int LCM(int a,int b){ return a/KGCD(a,b)*b; }
inline ll qpow(ll n,ll m){n%=mod;ll ans=1;while(m){if(m%2) ans=(ans*n)%mod;m/=2;n=(n*n)%mod;}return ans;}
inline ll inv2(ll b){return qpow(b,mod-2);}
inline ll inv(ll b){return b==1?1:(mod-mod/b)*inv(mod%b)%mod;}
int dir[5][2]={0,1,0,-1,1,0,-1,0};
long long a[100005];
long long b[100005];
long long tree[100005];
int n;
long long lowbit(long long x)
{
return x&(-x);
}
long long sum(long long x)
{
long long an
afdd
s=0;
while(x>0)
{
ans=(ans+tree[x])%mod;
x=x-lowbit(x);
}
return ans;
}
void add(long long x,long long valu)
{
while(x<=n)
{
tree[x]=(tree[x]+valu)%mod;
x=x+lowbit(x);
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(tree,0,sizeof(tree));
for(int i=0;i<n;i++)
{
scanf("%I64d",&a[i]);//FZ评测机用lld也是可以的 刚开始以为不行
b[i]=a[i];
}
sort(b,b+n);//讲数组排序后 进行离散化
for(int i=0;i<n;i++)
{
a[i]=lower_bound(b,b+n,a[i])-b+1;//查找下有多少个比他小的 但是树状数组最小从1开始所以加1
add(a[i],sum(a[i]-1)+1);
//然后开始讲a[i]这个点以后所有的点都加上他前边有多少比他小的和他本 身 }
long long ans=sum(n);//从上到下跑一边
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: