题目:http://www.codeforces.com/contest/283
A:对3个操作分别维护平均值ans。
操作1:更新数字总和,数字个数不变,更新ans,在cnt数组上打上标记来表示前ai个数的值要增加x
操作2:数字个数加1,数字总和加上新插入的数,更新ans
操作3:通过cnt数组更新最后一个数字的值,cnt相应位置上的标记往前移, 数字总和减去最后一个数字的值,数字个数减1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf=1<<29;
#define N 200010
int a[N],cnt[N];
int main()
{
int n,ch,x,y;
scanf("%d",&n);
int kk=1;
a[1]=0;
double ans=0;
for(int i=0;i<n;i++){
scanf("%d",&ch);
if(ch==1){
scanf("%d%d",&y,&x);
y=min(y,kk);
cnt[y]+=x;
ans+=y*x*1.0/kk;
}else if(ch==2){
scanf("%d",&x);
ans=(ans*kk+x)/(kk+1);
a[++kk]=x;
}else{
if(kk<2) continue;
ans=(ans*kk-cnt[kk]-a[kk])/(kk-1);
cnt[kk-1]+=cnt[kk];
cnt[kk]=0;
kk--;
}
printf("%.10lf\n",ans);
}
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf=1<<29;
#define N 200010
int vis[N][2];
ll dp[N][2];
int n,a[N];
ll dfs(int x,int k)
{
if(x<=0||x>n) return 0;
if(x==1) return -1;
if(vis[x][k]) return dp[x][k];
vis[x][k]=1;
ll ans=a[x];
int y;
if(k) y=x-a[x];
else y=x+a[x];
ll t=dfs(y,k^1);
if(t==-1) ans=-1;
else ans+=t;
return dp[x][k]=ans;
}
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,-1,sizeof(dp));
for(int i=2;i<=n;i++){
if(!vis[i][0]){
dfs(i,0);
}
if (!vis[i][1]) {
dfs(i, 1);
}
}
for(int i=1;i<=n-1;i++){
if(dp[i+1][1]==-1)
printf("%d\n",-1);
else printf("%I64d\n",dp[i+1][1]+i);
}
}
C:这题其实就是一个有附加条件的背包。考虑这样一个背包问题:n件物品,背包容量为t,要求第i+1件物品拿的比第i件物品多。将物品进行组合,第i件物品到第n件的组合作为第i件物品,这样原问题的要求就转换成了除第1件外的其他物品至少拿一件,这个额外的条件在dp过程中就很容易处理了。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf=1<<29;
#define N 100010
const int mod=1000000007;
int a[310];
vector<int> e[310];
int fa[310],next[310];
int val[310][310];
int dp[N];
int main()
{
int n,Q,T,x,y;
scanf("%d%d%d",&n,&Q,&T);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=0;i<Q;i++){
scanf("%d%d",&x,&y);
fa[y]=x;next[x]=y;
}
int kk=0,cnt=0;
for(int i=1;i<=n;i++){
if(next[i]==0){
int t=i;
while(t!=0){
e[kk].push_back(t);
cnt++;
t=fa[t];
if(t==i) break;
}
kk++;
}
}
if(cnt<n){
printf("0\n");
return 0;
}
for(int i=0;i<kk;i++){
int t=e[i].size()-1;
val[i][t]=a[e[i][t]];
for(int j=t-1;j>=0;j--){
val[i][j]=a[e[i][j]]+val[i][j+1];
}
}
dp[0]=1;
for(int i=0;i<kk;i++){
int t=e[i].size()-1;
for(int j=0;j<=t;j++){
int v=val[i][j];
if(j==0){
for(int k=v;k<=T;k++){
dp[k]+=dp[k-v];
dp[k]%=mod;
}
}else{
for(int k=T;k>=v;k--)
dp[k]=dp[k-v];
for(int k=0;k<min(v,T+1);k++) dp[k]=0;
for(int k=v;k<=T;k++){
dp[k]+=dp[k-v];
dp[k]%=mod;
}
}
}
}
printf("%d\n",dp[T]);
}
D:设dp[i]表示以a[i]为结尾的cool序列最多能不改变几个数字,如果a[i]为奇数,那么如果a[j]%a[i]==0(1<=j<i),dp[i]=max(dp[j]+1,dp[i]);如果a[i]为偶数,那么满足a[i-1]%a[i]==a[i]/2则dp[i-1]可以转移到dp[i] ,同理如果a[i-1]是偶数,dp[i-2]转移到dp[i-1]也是一样。也就是说dp[j]可以转移到dp[i]要满足a[j]%(a[i]/2^(i-j))==(a[i]/2^(i-j))/2(如果(a[i]/2^(i-j))一直是偶数)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf=1<<29;
ll a[5010];
int dp[5010];
int main()
{
int n,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%I64d",&a[i]);
dp[i]=1;
ll y=a[i];
for(int j=i-1;j>=1;j--){
if(y%2&&a[j]%y==0)
dp[i]=max(dp[j]+1,dp[i]);
if(y%2==0&&a[j]%y==y/2)
dp[i]=max(dp[j]+1,dp[i]);
y=y&1?y:y>>1;
}
ans=max(ans,dp[i]);
}
printf("%d\n",n-ans);
}