A、经典LIS模板(poj2533)
题意:求最长严格上升子序列
#include
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e3+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
int a[N],dp[N];
int main()
{
int n=read();for(int i=1;i<=n;++i)a[i]=read(),dp[i]=1;
int ans=1;
for(int i=2;i<=n;++i){
for(int j=1;j<i;++j)
if(a[j]<a[i])dp[i]=max(dp[j]+1,dp[i]);
ans=max(ans,dp[i]);
}
cout<<ans<<line;
return 0;
}
B、多阶段决策dp模板(hdu2059)
题意:长为L的赛道上,乌龟在电车有无电时的速度x、y能否比恒定速度v的兔子先到达终点,赛道上有n个带属性的充电站。
思路:相同路程比较时间,定义dp[i]为第j(ji));
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e2+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
double L,a[N],dp[N];
int main()
{
int n,s,t,v,x,y;
while(cin>>L){
cin>>n>>s>>t>>v>>x>>y;
for(int i=1;i<=n;++i)a[i]=read(),dp[i]=INT_MAX;
a[n+1]=L;dp[0]=0;dp[n+1]=INT_MAX;
for(int i=1;i<=n+1;++i)for(int j=0;j<i;++j){
double mx=0;
if(a[i]-a[j]>s)mx=(a[i]-a[j]-s)/y+s*1.0/x;
else mx=(a[i]-a[j])/x;
mx+=dp[j];
if(j)mx+=t;
dp[i]=min(dp[i],mx);
}
if(dp[n+1]<L/v)cout<<"What a pity rabbit!"<<line;
else cout<<"Good job,rabbit!"<<line;
}
return 0;
}
C、CodeForces - 1077A
题意:k次操作,加a减b依次进行,问最后结果
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e3+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
int main()
{
int T=read();
while(T--){
LL a=read(),b=read(),k=read();
LL ans=k/2*(a-b);
if(k&1)ans+=a;
cout<<ans<<line;
}
return 0;
}
D、CodeForces - 1077B
题意:各个公寓灯有0、1两种状态,形为101的公寓会受到干扰,求最小关掉灯的个数使各个公寓都不受干扰。
思路:实际就是找有多少个10101与101,最小关灯次数都为1,其他如1010101、101010101等等都可以转化为这两种情况,统计即可。
#include
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e2+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
int main()
{
string str="";int a;
int n=read();for(int i=1;i<=n;++i)a=read(),str+='0'+a;
str+="000000";int i=0,ans=0;
while(i<=n){
if(str.substr(i,5)=="10101")ans++,i+=4;
else if(str.substr(i,3)=="101")ans++,i+=2;
else i++;
}
cout<<ans<<line;
return 0;
}
E、CodeForces - 1077C
题意:n个数中判断是否可以删除某个数,使剩下数中的某个数是其他所有数的和
思路:记录总和,循环依次判断删除这个数能否满足条件
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=2e5+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
LL sum,a[N];
unordered_map<LL,int> mp;
int main()
{
int n=read();for(int i=1;i<=n;++i)a[i]=read(),sum+=a[i],mp[a[i]]++;
vector<int> V;
for(int i=1;i<=n;++i){
mp[a[i]]--;
LL t=sum-a[i];
if(!(t&1)&&mp[t/2])V.push_back(i);
mp[a[i]]++;
}
cout<<V.size()<<line;
for(auto it:V)cout<<it<<" ";
cout<<line;
return 0;
}
F、CodeForces - 1077D
题意:n个数中选出k个数,使这k个数在n个数的重复次数最多
思路:要求重复次数最多,直接二分重复次数判断此时满足重复次数的个数能否大于k个
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=2e5+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
unordered_map<int,int> mp;
int n,k,x;
bool judge(int t)
{
int num=0;
for(auto it:mp)num+=it.second/t;
return num>=k;
}
int main()
{
n=read(),k=read();for(int i=1;i<=n;++i)x=read(),mp[x]++;
int L=1,R=n,ans;
while(L<=R){
if(judge(mid)){
ans=mid;
L=mid+1;
}
else R=mid-1;
}
for(auto it:mp){
if(k==0)break;
int y=min(k,it.second/ans);
k-=y;
while(y--)cout<<it.first<<" ";
}
cout<<line;
return 0;
}
G、CodeForces - 1077E
题意:定义序列F:{x,2x,4x…}
长为n的数组a,根据a[i]出现的次数求最大满足序列F的序列和
思路:虽然a[i]范围达到1e9但各个a[i]出现次数最多为n,可以选择F序列的第一项进行二分
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=2e5+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
map<int,int> mp;
int a[N];
int main()
{
int n=read(),x;for(int i=1;i<=n;++i)x=read(),mp[x]++;
int k=0,m=0;LL ans=0;
for(auto it:mp)a[++k]=it.second,m=max(m,a[k]);
sort(a+1,a+k+1);
for(int i=1;i<=m;++i){
int t=i,L=1;
LL sum=0;
while(1){
L=lower_bound(a+L,a+k+1,t)-a;
if(L>k)break;
L++;
sum+=t;
t<<=1;
}
ans=max(ans,sum);
}
cout<<ans<<line;
return 0;
}
H、CodeForces - 1077F1
题意:求n个数中选出x个数最大和,但任意连续k个数中必须有选中的.
思路:定义dp[i][j]为前i个数中选j个的最大值,其中第i个必选,又因有k的限制,最后k个数必有一选才能合法化
转移方程dp[i][j]=max(dp[i][j],dp[p][j-1]+a[i])其中max(0,i-k)<=p
#include
I、CodeForces - 1077F2
单调队列维护dp[p][j-1]单增
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=5e3+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
#define inf 0x3f3f3f3f3f3f3f3f
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
LL dp[N][N],a[N],Q[N],que[N];
int main()
{
int n=read(),k=read(),x=read();
for(int i=1;i<=n;++i)a[i]=read();
LL ans=-1;memset(dp,-inf,sizeof(dp));
dp[0][0]=0;
for(int j=1;j<=x;++j){
int L=0,R=1;Q[0]=0;
for(int i=1;i<=n;++i){
while(L<R&&Q[L]<i-k)L++;
dp[i][j]=dp[Q[L]][j-1]+a[i];
while(L<R&&dp[i][j-1]>=dp[Q[R-1]][j-1])R--;
Q[R++]=i;
}
}
for(int i=n-k+1;i<=n;++i)ans=max(ans,dp[i][x]);
cout<<ans<<line;
return 0;
}