hdu5494 Problem 0. Card Game
怎么选择m个数都能赢,最小的m个数之和大于对方的最大的m个数之和就好了。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#define rep(i,n) for(i=0;i<n;i++)
#define cle(x) memset(x,0,sizeof(x))
#define ll long long
const int maxn=1000+5;
using namespace std;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int T;
cin>>T;
int a[maxn],b[maxn],n,m;
while(T--){
cin>>n>>m;
int i;rep(i,n)cin>>a[i];
rep(i,n)cin>>b[i];
int sum[maxn];
sort(a,a+n);sort(b,b+n);
int ip=0;rep(i,n){
if(i==0)sum[i]=a[i];
else sum[i]=sum[i-1]+a[i];
}
int sumb[maxn];
for(i=n-1;i>=0;i--){
if(i==n-1)sumb[ip++]=b[i];
else sumb[ip++]=sumb[ip-1]+b[i];
}
if(sum[m-1]>sumb[m-1])cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
hdu 5495 Problem 1. LCS
题意
子序列,按照相同的排列顺序,重新排列,是相同子序列最长。
解法
每个环之间是独立的,在独立的一个环上的选择,最优情况要舍掉一个数字,比如1->2 2->3 3->4 4->1 序列(1,2,3,4)和序列(2,3,4,1)就要舍掉1
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#define rep(i,n) for(i=0;i<n;i++)
#define cle(x) memset(x,0,sizeof(x))
#define ll long long
const int maxn=100000+5;
using namespace std;
int a[maxn],b[maxn],u[maxn];
int v[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int T;
cin>>T;
int n;
while(T--)
{
cle(v);
cin>>n;
int i;
rep(i,n)
{
scanf("%d",&a[i]);
}
rep(i,n)
{
scanf("%d",&b[i]);
}
rep(i,n)
{
u[a[i]]=b[i];
}
int ans=0;
rep(i,n)
{
if(a[i]==b[i])
{
ans++;
v[a[i]]=1;
continue;
}
if(v[a[i]]==0)
{
v[a[i]]=1;
int temp=1;
int now=u[a[i]];
while(true)
{
if(v[now])
{
break;
}
else
{
v[now]=1;
temp++;
now=u[now];
}
}
ans+=temp;
ans--;
}
}
cout<<ans<<endl;
}
return 0;
}
hdu 5496 Problem 2. Beauty of Sequence
题意:
所有子序列和之和,子序列中连续相邻相同元素只算一次。
解法:
官方解法:一个数的如果是几个连续相同数的第一个,他的贡献计算。
总的方案数=之前的方案数*之后的方案数
之前的方案数=所有方案数-以和他相同数作为倒数第二个的方案数 用map统计就好了
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#define rep(i,n) for(i=0;i<n;i++)
#define cle(x) memset(x,0,sizeof(x))
#define ll long long
const int maxn=100000+5;
const int mod=1e9+7;
using namespace std;
ll a[maxn];
ll b[maxn];
int n;
void init()
{
b[0]=0;
for(int i=1;i<maxn;i++){
b[i]=(b[i-1]*2+1)%mod;
}
}
map<ll,ll>mp;
void doit()
{
mp.clear();ll sum=0;
for(int i=1;i<=n;i++)
{
ll be=(b[i-1]+1-mp[a[i]]+mod)%mod;//之前的
ll en=b[n-i]+1;//之后的
sum=((sum+((a[i]*((be*en)%mod))%mod))%mod);
mp[a[i]]=(mp[a[i]]+b[i-1]+1)%mod;
}
cout<<sum<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int T;cin>>T;init();
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++){
scanf("%I64d",&a[i]);
}
doit();
}
return 0;
}
hdu 5497 Problem 3. Inversion
题意:
一个序列 ,可以删除一个长度为m的连续子序列. 问如何删除才能使逆序对最少。
解法:
删掉的应该是构成逆序对最多那些
向前连线(比他大的)
向后两线(比他小的)
选择的区间可能重复计算了。连接的两端都在区间内。
删掉的数目=所有的连线(每个数向前连线+向后连线)-区间内构成的逆序对个数(一个树状数组可维护,能想到怎么维护就可以解决了)
备注:
由于我自己写的思路比较露骨,所以有时提交超时有时候AC,可以加一些输入输出挂之类的~
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#define rep(i,n) for(i=0;i<n;i++)
#define cle(x) memset(x,0,sizeof(x))
#define ll long long
const int maxn=100000+5;
using namespace std;
ll a[maxn],rea[maxn];
ll b[maxn],qu[maxn];
ll sum[maxn];
int lowbit(int x){
return x&(-x);
}
ll getsum(int x)
{
ll re=0;
for(int i=x-1;i>0;i-=lowbit(i))re+=sum[i];
return re;
}
void update(int x,ll y){
for(int i=x;i<maxn;i+=lowbit(i))sum[i]+=y;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int T;
cin>>T;
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
int i;
rep(i,n){
scanf("%I64d",&a[i]);rea[i]=n-a[i]+1;}
cle(sum);ll cot=0;
for(i=n-1;i>=0;i--){
b[i]=getsum(a[i]);cot+=b[i];
update(a[i],1);
}
if(m==0||cot==0){
printf("%I64d\n",cot);
continue;
}
cle(sum);
rep(i,n){
b[i]+=getsum(rea[i]);//每个位置构成逆序对,向前向后之和
update(rea[i],1);
}
cle(sum);qu[0]=0;
for(i=0;i<m;i++){
qu[0]+=getsum(rea[i]);//维护第一个m个连续的数的逆序对个数
update(rea[i],1);
}int ip=1;
for(i=1;i<=n-m;i++){
qu[ip]=qu[ip-1]-(getsum(n+1)-getsum(rea[i-1]+1));//去掉第一个数的构成个数
update(rea[i-1],-1);
qu[ip]+=getsum(rea[i+m-1]);//加上最新数构成个数
update(rea[i+m-1],1);
ip++;
}
ll maxans=0;ll now=0;
for(i=0;i<m;i++)now+=b[i];
for(i=0;i<=n-m;i++){
maxans=max(maxans,now-qu[i]);
now-=b[i];now+=b[i+m];
}
printf("%I64d\n",cot-maxans);
}
return 0;
}
hdu 5498 Problem 4. Tree
现如今能力不足~