BZOJ 4236 JOIOJI

f[i][0..2]表示前i个字符中′J′/′O′/′I′的个数

将二元组<f[i][0]−f[i][1],f[i][1]−f[i][2]>扔进map,记录一下最早出现的时间

对于每一个位置去map里面查一下就可以

时间复杂度O(nlogn)

#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
int n,ans;
char s[M];
map<pair<int,int>,int> m;
int sum[3][M];
int main()
{
int i;
cin>>n;
scanf("%s",s+1);
m[make_pair(0,0)]=0;
for(i=1;i<=n;i++)
{
sum[0][i]=sum[0][i-1]+(s[i]=='J');
sum[1][i]=sum[1][i-1]+(s[i]=='O');
sum[2][i]=sum[2][i-1]+(s[i]=='I');
if( m.find( make_pair(sum[0][i]-sum[1][i],sum[1][i]-sum[2][i]) )==m.end() )
m[make_pair(sum[0][i]-sum[1][i],sum[1][i]-sum[2][i])]=i;
else
ans=max(ans,i-m[make_pair(sum[0][i]-sum[1][i],sum[1][i]-sum[2][i])]);
}
cout<<ans<<endl;
return 0;
}

BZOJ 4237 稻草人

按y坐标分治。每层分治内部按x坐标排序后。上层维护一个单调递减的单调栈,下层维护一个单调递增的单调栈

然后对于上层每一个元素去下层二分就可以

时间复杂度O(nlog2n)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std; struct Point{
int x,y;
friend istream& operator >> (istream &_,Point &p)
{
return scanf("%d%d",&p.x,&p.y),_;
}
}points[M],_points[M];
bool Compare_x (const Point &p1,const Point &p2)
{
return p1.x < p2.x ;
}
bool Compare_y (const Point &p1,const Point &p2)
{
return p1.y < p2.y ;
} int n;
long long ans;
Point stack1[M],stack2[M];
int top1,top2; void Divide_And_Conquer(int l,int r)
{
if(l==r) return ;
int i,j,mid=l+r>>1;
int _l=l,_r=mid+1;
for(i=l;i<=r;i++)
if(points[i].y<=mid)
_points[_l++]=points[i];
else
_points[_r++]=points[i];
memcpy(points+l,_points+l,sizeof(Point)*(r-l+1) );
for(top1=top2=0,j=l,i=mid+1;i<=r;i++)
{
for(;j<=mid&&points[j].x<points[i].x;j++)
{
while(top2&&points[j].y>stack2[top2].y)
top2--;
stack2[++top2]=points[j];
}
while(top1&&points[i].y<stack1[top1].y)
top1--;
stack1[++top1]=points[i];
int pos=upper_bound(stack2+1,stack2+top2+1,stack1[top1-1],Compare_x)-stack2;
ans+=top2-pos+1;
}
Divide_And_Conquer(l,mid);
Divide_And_Conquer(mid+1,r);
} int main()
{
static pair<int,int*> b[M];
int i;
cin>>n;
for(i=1;i<=n;i++)
cin>>points[i]; for(i=1;i<=n;i++)
b[i]=make_pair(points[i].x,&points[i].x);
sort(b+1,b+n+1);
for(i=1;i<=n;i++)
*b[i].second=i; for(i=1;i<=n;i++)
b[i]=make_pair(points[i].y,&points[i].y);
sort(b+1,b+n+1);
for(i=1;i<=n;i++)
*b[i].second=i; sort(points+1,points+n+1,Compare_x);
Divide_And_Conquer(1,n);
cout<<ans<<endl;
return 0;
}

BZOJ 4238 电压

看到这题想要直接上动态二分图的举手……

任选一棵生成树。考虑选择树边或者非树边

定义一条非树边为好边当且仅当两个端点在树上的距离为奇数。否则为坏边

假设坏边仅仅有一条那么这条坏边是可选的

假设一条树边被全部的坏边覆盖并且不被好边覆盖那么这条边是可选的

DFS一遍就可以

因为DFS树没有横叉边仅仅有返祖边因此求LCA是O(1)的 这样复杂度就是O(n+m)的了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
struct abcd{
int to,next;
}table[M<<1];
int head[M],tot=1;
int n,m,ans,good_cnt,bad_cnt;
int dpt[M],fa[M],good[M],bad[M];
bool v[M];
void Add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void DFS(int x,int from)
{
int i;
v[x]=true;
dpt[x]=dpt[fa[x]]+1;
for(i=head[x];i;i=table[i].next)
if(i^from^1)
{
if(!v[table[i].to])
{
fa[table[i].to]=x;
DFS(table[i].to,i);
good[x]+=good[table[i].to];
bad[x]+=bad[table[i].to];
}
else
{
if(dpt[table[i].to]>dpt[x])
continue;
if(dpt[x]-dpt[table[i].to]&1)
good[x]++,good[table[i].to]--,good_cnt++;
else
bad[x]++,bad[table[i].to]--,bad_cnt++;
}
}
}
int main()
{
int i,x,y;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
Add(x,y);
Add(y,x);
}
for(i=1;i<=n;i++)
if(!v[i])
DFS(i,0);
for(i=1;i<=n;i++)
if(fa[i]&&bad[i]==bad_cnt&&!good[i])
++ans;
if(bad_cnt==1)
++ans;
cout<<ans<<endl;
}

BZOJ 4239 巴士走读

将二元组<网站,时间>看做一个点,那么点数是O(m)的

每辆巴士连一条边。每一个点向下一个时间连边,然后将全部边反向

枚举终点站的每一个时间。增加队列广搜,得到最晚多久到达1号网站能够在这个时间到达终点站

然后对于每一个询问去数组中二分就可以

时间复杂度O((m+q)logm)

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std; namespace Hash_Set{
struct List{
int x,y,val;
List *next;
List(int _,int __,List *___):
x(_),y(__),val(0),next(___) {}
}*head[3001][3001];
int& Hash(int x,int y)
{
int pos1=x%3001;
int pos2=y%3001;
List *temp;
for(temp=head[pos1][pos2];temp;temp=temp->next)
if(temp->x==x&&temp->y==y)
return temp->val;
return (head[pos1][pos2]=new List(x,y,head[pos1][pos2]))->val;
}
} struct abcd{
int to,next;
}table[900900];
int head[600600],tot; int n,m,k,now=-1;
pair<int,int> ans[600600];int top; vector<int> stack[M]; int T;
pair<int,int> hash[600600]; bool v[600600];
int q[600600],r,h; void Add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
int Hash(int x,int y)
{
int &val=Hash_Set::Hash(x,y);
if( !val )
hash[val=++T]=make_pair(x,y);
return val;
}
void BFS()
{
int i;
while(r!=h)
{
int x=q[++h];
for(i=head[x];i;i=table[i].next)
if(!v[table[i].to])
{
v[table[i].to]=true;
q[++r]=table[i].to;
}
if(hash[x].first==1)
now=max(now,hash[x].second);
}
}
int main()
{
int i,j,x,y,_x,_y;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&_x,&_y);
stack[x].push_back(_x);
stack[y].push_back(_y);
Add( Hash(y,_y) , Hash(x,_x) );
}
for(i=1;i<=n;i++)
{
sort(stack[i].begin(),stack[i].end());
for(j=1;j<(signed)stack[i].size();j++)
if( stack[i][j]!=stack[i][j-1] )
Add( Hash(i,stack[i][j]) , Hash(i,stack[i][j-1]) );
}
for(i=0;i<(signed)stack[n].size();i++)
{
int temp=Hash(n,stack[n][i]);
if(v[temp]) continue;
v[temp]=true;q[++r]=temp;
BFS();
ans[++top]=make_pair(stack[n][i],now);
}
ans[0].second=-1;
cin>>k;
for(i=1;i<=k;i++)
{
scanf("%d",&x);
printf("%d\n",(lower_bound(ans+1,ans+top+1,pair<int,int>(x,0x3f3f3f3f) )-1)->second);
}
return 0;
}

BZOJ 4240 有趣的家庭菜园

从小到大枚举高度,因为不管将这株草移动到左側还是右側都对照它高的植物没有影响,因此贪心选择代价最小的方向就可以

故答案为∑min(a[1…i-1]中大于a[i]的数的数量,a[i+1…n]中大于a[i]的数的数量)

用树状数组就可以 时间复杂度O(nlogn)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 300300
using namespace std;
int n,m,a[M],f[M],g[M];
long long ans;
namespace BIT{
int c[M];
void Initialize()
{
memset(c,0,sizeof c);
}
void Update(int x)
{
for(;x;x-=x&-x)
c[x]++;
}
int Query(int x)
{
int re=0;
for(;x<=m;x+=x&-x)
re+=c[x];
return re;
}
}
int main()
{
static pair<int,int*> b[M];
int i;
cin>>n;
for(i=1;i<=n;i++)
{
scanf("%d",&b[i].first);
b[i].second=&a[i];
}
sort(b+1,b+n+1);
for(i=1;i<=n;i++)
{
if(i==1||b[i].first!=b[i-1].first)
++m;
*b[i].second=m;
} for(i=1;i<=n;i++)
{
BIT::Update(a[i]);
f[i]=BIT::Query(a[i]+1);
} BIT::Initialize();
for(i=n;i;i--)
{
BIT::Update(a[i]);
g[i]=BIT::Query(a[i]+1);
} for(i=1;i<=n;i++)
ans+=min(f[i],g[i]);
cout<<ans<<endl; return 0;
}

BZOJ 4241 历史研究

分块,记录第i块到第j块的答案以及前i块中数字j出现了多少次,然后每次询问先调用整块的答案,然后枚举零碎的部分进行更新就可以

时间复杂度O(qn√)

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
#define B 350
using namespace std;
int n,m,q,b;
int a[M],ori[M];
int l[B],r[B],belong[M];
int block_cnt[B][M];//block_cnt[i][j]表示前i块中数字j的出现次数
long long block_ans[B][B];//block_ans[i][j]表示从第i块到第j块的最大重要度
long long Query(int l,int r)
{
static int cnt[M],tim[M],T;
int i,_l=belong[l],_r=belong[r];
long long re=block_ans[_l+1][_r-1];
++T;
if(_l==_r)
{
for(i=l;i<=r;i++)
{
if(tim[a[i]]!=T)
tim[a[i]]=T,cnt[a[i]]=0;
re=max(re,(long long)ori[a[i]]*++cnt[a[i]]);
}
return re;
}
for(i=l;i<=::r[_l];i++)
{
if(tim[a[i]]!=T)
tim[a[i]]=T,cnt[a[i]]=block_cnt[_r-1][a[i]]-block_cnt[_l][a[i]];
re=max(re,(long long)ori[a[i]]*++cnt[a[i]]);
}
for(i=r;i>=::l[_r];i--)
{
if(tim[a[i]]!=T)
tim[a[i]]=T,cnt[a[i]]=block_cnt[_r-1][a[i]]-block_cnt[_l][a[i]];
re=max(re,(long long)ori[a[i]]*++cnt[a[i]]);
}
return re;
}
int main()
{
static pair<int,int*> c[M];
int i,j,x,y; cin>>n>>q;
b=int(sqrt(n)+1e-7); for(i=1;i<=n;i++)
{
scanf("%d",&c[i].first);
c[i].second=&a[i];
}
sort(c+1,c+n+1);
for(i=1;i<=n;i++)
{
if(i==1||c[i].first!=c[i-1].first)
ori[++m]=c[i].first;
*c[i].second=m;
} for(i=1;i<=n;i++)
belong[i]=(i-1)/b+1;
for(i=1;(i-1)*b+1<=n;i++)
l[i]=(i-1)*b+1,r[i]=min(i*b,n); for(i=1;i<=n;i++)
block_cnt[belong[i]][a[i]]++;
for(i=1;l[i];i++)
for(j=1;j<=n;j++)
block_cnt[i][j]+=block_cnt[i-1][j];
static int cnt[M];
long long ans;
for(i=1;l[i];i++)
{
memset(cnt,0,sizeof cnt);ans=0;
for(j=l[i];j<=n;j++)
{
ans=max(ans,(long long)ori[a[j]]*++cnt[a[j]]);
if(j==r[belong[j]])
block_ans[i][belong[j]]=ans;
}
} for(i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
#ifdef ONLINE_JUDGE
printf("%lld\n",Query(x,y));
#else
printf("%I64d\n",Query(x,y));
#endif
}
return 0;
}

BZOJ 4242 水壶

把每栋建筑物扔进队列跑BFS,对于每块空地记录这块空地是被哪栋建筑物搜到的。以及距离是多少

然后不同所属的空地之间连边,跑货车运输就可以

时间复杂度O(whα(p)+qlogp)

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
int n,m,k,Q;
char map[2020][2020];
pair<int,int> v[2020][2020];
pair<int,int> q[4004004];int r,h;
vector< pair<int,int> > stack[4004004];
int fa[M],dis[M],dpt[M];
void BFS()
{
int i;
while(r!=h)
{
pair<int,int> x=q[++h];
for(i=0;i<4;i++)
{
pair<int,int> y(x.first+dx[i],x.second+dy[i]);
if( y.first==0 || y.second==0 || y.first==n+1 || y.second==m+1 || map[y.first][y.second]=='#' )
continue;
if( v[y.first][y.second]==pair<int,int>(0,0) )
q[++r]=y,v[y.first][y.second]=pair<int,int>(v[x.first][x.second].first+1,v[x.first][x.second].second);
else if(v[y.first][y.second].second!=v[x.first][x.second].second)
stack[v[y.first][y.second].first+v[x.first][x.second].first].push_back(pair<int,int>(v[y.first][y.second].second,v[x.first][x.second].second));
}
}
}
namespace Union_Find_Set{
int fa[M],rank[M];
int Find(int x)
{
if(!fa[x]||fa[x]==x)
return fa[x]=x;
return fa[x]=Find(fa[x]);
}
}
void Kruskal()
{
using namespace Union_Find_Set;
int i,j;
for(i=0;i<=n*m;i++)
for(j=0;j<(signed)stack[i].size();j++)
{
int x=Find(stack[i][j].first);
int y=Find(stack[i][j].second);
if(x==y)
continue;
if(rank[x]>rank[y])
swap(x,y);
if(rank[x]==rank[y])
++rank[y];
Union_Find_Set::fa[x]=y;
::fa[x]=y;dis[x]=i;
}
}
int Depth(int x)
{
if(dpt[x])
return dpt[x];
if(!fa[x])
return dpt[x]=1;
return dpt[x]=Depth(fa[x])+1;
}
int Query(int x,int y)
{
if( Union_Find_Set::Find(x)!=Union_Find_Set::Find(y) )
return -1;
int re=0;
if(Depth(x)<Depth(y))
swap(x,y);
while(Depth(x)>Depth(y))
re=max(re,dis[x]),x=fa[x];
while(x!=y)
re=max(re,dis[x]),re=max(re,dis[y]),x=fa[x],y=fa[y];
return re;
}
int main()
{
int i,x,y;
cin>>n>>m>>k>>Q;
for(i=1;i<=n;i++)
scanf("%s",map[i]+1);
for(i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
v[x][y]=pair<int,int>(0,i);
q[++r]=pair<int,int>(x,y);
}
BFS();
Kruskal();
for(i=1;i<=Q;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",Query(x,y));
}
return 0;
}

BZOJ 4243 交朋友

把能进行会议的国家之间都用并查集连接起来。然后把每一个进行过会议的国家扔进队列跑BFS,将搜到的国家用并查集连接

终于答案等于每一个单点的出度个数+2*C(每一个集合的大小,2)

时间复杂度O((n+m)α(n))

#include <set>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n,m;
long long ans;
set<int> map[M];
bool v[M];
int q[M],r,h;
namespace Union_Find_Set{
int fa[M],rank[M],size[M];
int Find(int x)
{
if(!fa[x])
fa[x]=x,size[x]=1;
if(fa[x]==x)
return x;
return fa[x]=Find(fa[x]);
}
void Union(int x,int y)
{
x=Find(x);y=Find(y);
if(x==y) return ;
if(rank[x]>rank[y])
swap(x,y);
if(rank[x]==rank[y])
++rank[y];
fa[x]=y;size[y]+=size[x];
}
}
int main()
{
using namespace Union_Find_Set;
int i,x,y;
set<int>::iterator it;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
map[x].insert(y);
}
for(i=1;i<=n;i++)
for(it=map[i].begin();it!=map[i].end();it++)
if( map[*it].find(i)!=map[*it].end() )
Union(i,*it);
for(i=1;i<=n;i++)
if(map[i].size()>1)
{
int temp=*map[i].begin();
for(it=map[i].begin(),it++;it!=map[i].end();it++)
Union(*it,temp);
}
for(i=1;i<=n;i++)
if(size[Find(i)]!=1)
v[i]=1,q[++r]=i;
while(r!=h)
{
x=q[++h];
for(it=map[x].begin();it!=map[x].end();it++)
{
Union(x,*it);
if(!v[*it]) v[*it]=true,q[++r]=*it;
}
}
for(i=1;i<=n;i++)
if(Find(i)==i)
{
if(size[i]==1)
ans+=map[i].size();
else
ans+=(long long)size[i]*(size[i]-1);
}
cout<<ans<<endl;
return 0;
}

BZOJ 4244 邮戳拉力赛

从车站0沿上行车道到达车站n的路径必走,除掉这条路径后图中剩下了一些环

令fi,j表示已经经过了前i个邮戳台,并且从下行站台走到上行站台的次数-从上行站台走到下行站台的次数为j的最短时间

每层跑个全然背包就可以 时间复杂度O(n2)

顺便吐槽:官方能把スタンプラリー后面凝视一个“Collecting Stamps”我真是醉如烂泥。。。

谁能告诉我Stamp Rally究竟咋翻译……

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 3030
using namespace std;
int n,t;
long long f[M][M];
//f[i][j]表示已经到达过第1...i个邮戳,剩余的从上行站台走到下行站台的次数为j的最短时间
int u[M],v[M],d[M],e[M];
int main()
{
int i,j;
cin>>n>>t;
for(i=1;i<=n;i++)
scanf("%d%d%d%d",&u[i],&v[i],&d[i],&e[i]);
memset(f,0x3f,sizeof f);
f[0][0]=0;
for(i=1;i<=n;i++)
{
for(j=0;j<=n;j++)
f[i-1][j]+=j*t*2;
for(j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i-1][j-1]+d[i]+v[i]);
for(j=0;j<n;j++)
f[i][j]=min(f[i][j],f[i-1][j+1]+u[i]+e[i]);
for(j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i-1][j]+d[i]+e[i]);
for(j=0;j<=n;j++)
f[i][j]=min(f[i][j],f[i-1][j]+u[i]+v[i]);
for(j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][j-1]+d[i]+v[i]);
for(j=n-1;~j;j--)
f[i][j]=min(f[i][j],f[i][j+1]+u[i]+e[i]);
}
cout<<f[n][0]+t*(n+1)<<endl;
return 0;
}

BZOJ 4246 两个人的星座

这应该是这次合宿最难的一道题了……

考虑两个三角形。假设这两个三角形相离,那么一定能够做出两条内公切线,否则做不出来

枚举一个点,以这个点为中心按极角序枚举还有一个点。连接这两个点作出一条公切线,那么这两个三角形分别分布在这条线的两端,统计出两側每种颜色的点之后乘法原理就可以

时间复杂度O(n2logn)

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 3030
#define PI 3.1415926535897932384626433832795028841971
using namespace std;
struct Point{
int x,y;
Point() {}
Point(int _,int __):
x(_),y(__) {}
friend Point operator + (const Point &p1,const Point &p2)
{
return Point(p1.x+p2.x,p1.y+p2.y);
}
friend Point operator - (const Point &p1,const Point &p2)
{
return Point(p1.x-p2.x,p1.y-p2.y);
}
friend double Arctan2(const Point &p)
{
double re=atan2(p.y,p.x);
if(re<=0) re+=PI;
return re;
}
}O;
pair<Point,int> points[M],stack[M];
int n,top;
long long ans;
void Calculate(int c)
{
static pair<double,int> b[M];
static bool v[M];
static pair<Point,int> _stack[M];
int i,cnt[2][3]={{0,0,0},{0,0,0}};
for(i=1;i<=top;i++)
b[i]=pair<double,int>(Arctan2(stack[i].first-O),i);
sort(b+1,b+top+1);
for(i=1;i<=top;i++)
_stack[i]=stack[b[i].second];
memcpy(stack+1,_stack+1,sizeof(stack[0])*top);
for(i=1;i<=top;i++)
if( stack[i].first.y<O.y || stack[i].first.y==O.y && stack[i].first.x>O.x )
cnt[v[i]=false][stack[i].second]++;
else
cnt[v[i]=true][stack[i].second]++;
for(i=1;i<=top;i++)
{
cnt[v[i]][stack[i].second]--;
int cnt0=1,cnt1=1;
if(c!=0) cnt0*=cnt[false][0];
if(c!=1) cnt0*=cnt[false][1];
if(c!=2) cnt0*=cnt[false][2];
if(stack[i].second!=0) cnt1*=cnt[true][0];
if(stack[i].second!=1) cnt1*=cnt[true][1];
if(stack[i].second!=2) cnt1*=cnt[true][2];
ans+=(long long)cnt0*cnt1;
cnt0=cnt1=1;
if(c!=0) cnt0*=cnt[true][0];
if(c!=1) cnt0*=cnt[true][1];
if(c!=2) cnt0*=cnt[true][2];
if(stack[i].second!=0) cnt1*=cnt[false][0];
if(stack[i].second!=1) cnt1*=cnt[false][1];
if(stack[i].second!=2) cnt1*=cnt[false][2];
ans+=(long long)cnt0*cnt1;
cnt[v[i]^=1][stack[i].second]++;
}
}
int main()
{
int i,j;
cin>>n;
for(i=1;i<=n;i++)
scanf("%d%d%d",&points[i].first.x,&points[i].first.y,&points[i].second);
for(i=1;i<=n;i++)
{
top=0;
for(j=1;j<=n;j++)
if(i!=j)
stack[++top]=points[j];
O=points[i].first;
Calculate(points[i].second);
}
cout<<ans/4<<endl;
return 0;
}

BZOJ 4247 挂饰

傻逼背包

时间复杂度O(n2)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 2020
using namespace std;
int n;
struct Array{
long long a[M<<1];
long long& operator [] (int x)
{
return a[min(max(x,-n),n)+2000];
}
}f;
int main()
{
int i,j,x,y;
memset(&f,0xef,sizeof f);
cin>>n;f[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
x=1-x;
if(x>0)
{
for(j=n;j>=-n;j--)
f[j+x]=max(f[j+x],f[j]+y);
}
else
{
for(j=-n;j<=n;j++)
f[j+x]=max(f[j+x],f[j]+y);
}
}
long long ans=0;
for(i=-n;i<=1;i++)
ans=max(ans,f[i]);
cout<<ans<<endl;
return 0;
}

BZOJ 4236~4247 题解的更多相关文章

  1. BZOJ 1179 Atm 题解

    BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来 ...

  2. BZOJ 4236: JOIOJI MAP

    4236: JOIOJI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.ph ...

  3. BZOJ 4236 JOIOJI(前缀和)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4236 [题目大意] 给出一个只包含三种字母的字符串,求出三种字母数量相等的最长子串 [ ...

  4. BZOJ 4236 "JOIOJI"(前缀和+map+pair)

    传送门: [1]:BZOJ [2]:洛谷 •题解 定义数组 a,b,c 分别表示 'J' , 'O' , 'I' 的前缀和: 要想使区间 (L,R] 满足条件当且仅当 a[R]-a[L] = b[R] ...

  5. Bzoj 2064 分裂 题解

    2064: 分裂 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 570  Solved: 350[Submit][Status][Discuss] De ...

  6. BZOJ 4472 salesman 题解

    题目 某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇之间都只有唯一的可能经过其它城镇的路线.小T可以准确地估计出在每个城镇停留的净收益.这些净收益可能是负数,即推销商品的 ...

  7. BZOJ 4236: JOIOJI

    Description 给出一个字符串,只包含3个字母,询问最长的一个子串,3个字母出现次数相同. Sol map. 如果一个子串满足条件,那么它端点处的三个字母的个数两两差值都是一样的,直接存个状态 ...

  8. BZOJ 4236: JOIOJI map瞎搞

    分别记录J,O,I,的个数 cnt[char][i] 表示处理到第i位,char的个数 显然当且仅当 cnt[J][i] - cnt[O][i] == cnt[J][j-1] - cnt[O][j-1 ...

  9. bzoj 4236: JOIOJI【前缀和+map】

    设sj,so,si分别是J O I的个数前缀和,然后要求求最长(l,r)满足sj[r]-sj[l-1]==so[r]-so[l-1]==si[r]-si[l-1],化简一下就是满足so[r]-so[l ...

随机推荐

  1. php的更新

    因为 PHP 那“集百家之长”的蛋疼语法,加上社区氛围不好,很多人对新版本,新特征并无兴趣.本文将会介绍自 PHP5.2 起,直至 PHP5.6 中增加的新特征 本文目录:PHP5.2 以前:auto ...

  2. debian 9 配置ati驱动

    可以参考debian wiki 1.识别自己显卡驱动 lspci -nn | grep VGA 2.添加源 # Debian "stretch" deb http://httpre ...

  3. 一个学习scrapy的网站

    当然是scrapy中文网辣,从浅到深,例子报错几乎都有 http://www.scrapyd.cn/doc/

  4. JQuery封装ajax的方法

    1.$.post方法 $.post(url[,data][,callback][,type]) url:请求的后台程序地址 data:发送到后台的数据 callback:载入成功时回调函数,该函数参数 ...

  5. 洛谷 P1461 海明码 Hamming Codes

    P1461 海明码 Hamming Codes 题目描述 给出 N,B 和 D,要求找出 N 个由0或1组成的编码(1 <= N <= 64),每个编码有 B 位(1 <= B &l ...

  6. [CSS3] CSS Background Images

    Body with background image and gradient html { background: linear-gradient(#000, white) no-repeat; h ...

  7. poj 2612 Mine Sweeper

    Mine Sweeper Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6429   Accepted: 2500 Desc ...

  8. 计算机网络 4.网络层与IP协议

    网络中的每一台主机和路由器都有一个网络层部分.而路由器中也没有网络层以上的层次.网络层是协议栈中最复杂的层次. 转发forwarding:当一个分组到达某路由器的输入链路时.该路由器将分组移动到适当的 ...

  9. [雅礼NOIP2018集训 day3]

    考试的时候刚了T1两个小时线段树写了三个子任务结果发现看错了题目,于是接下来一个半小时我自闭了 result=历史新低 这告诉我们,打暴力要端正态度,尤其是在发现自己之前出锅的情况下要保持心态的平和, ...

  10. Swift学习笔记(6):控制流

    目录: For-In While If-Else, Guard-Else Switch 控制转移 For-In 可以使用for-in语句循环遍历集合.区间.元组.字符串. // 遍历区间,返回元素值 ...