300
预处理,这道题目和DIV2的最后一题类似,是那道题目的简化版。
// BEGIN CUT HERE
// END CUT HERE
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <ctime>
#include <utility>
#include <iterator>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef set<int> si;
typedef map<int,int> mii;
typedef map<string,int> msi;
typedef pair<int,int> pii;
typedef priority_queue<int,vector<int>,greater<int> > pless;
typedef priority_queue<int> pgreater;
#define clr(x,a) memset(x,a,sizeof(x))
#define sz(x) (int)x.size()
#define pb push_back
#define mp make_pair
#define REP(i,n) for(i=0;i<(n);++i)
#define FOR(i,l,h) for(i=(l);i<=(h);++i)
#define FORD(i,h,l) for(i=(h);i>=(l);--i)
class UniformBoard
{
public:
int sa[55][55];
int sp[55][55];
int se[55][55];
int getBoard(vector <string> board, int K)
{
int i,j,k;
int n=sz(board);
clr(sa,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int ret=0;
if(board[i-1][j-1]=='A') ret=1;
sa[i][j]=sa[i-1][j]+sa[i][j-1]-sa[i-1][j-1]+ret;
}
clr(sp,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int ret=0;
if(board[i-1][j-1]=='P') ret=1;
sp[i][j]=sp[i-1][j]+sp[i][j-1]-sp[i-1][j-1]+ret;
}
clr(se,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int ret=0;
if(board[i-1][j-1]=='.') ret=1;
se[i][j]=se[i-1][j]+se[i][j-1]-se[i-1][j-1]+ret;
}
int res=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int x=i;x<=n;x++)
for(int y=j;y<=n;y++){
int l=y-j+1;
int w=x-i+1;
if(l*w>sa[n][n]) continue;
int a=sa[x][y]-sa[x][j-1]-sa[i-1][y]+sa[i-1][j-1];
int p=sp[x][y]-sp[x][j-1]-sp[i-1][y]+sp[i-1][j-1];
int e=se[x][y]-se[x][j-1]-se[i-1][y]+se[i-1][j-1];
int step=0;
if(e!=0) step+=e;
if(p!=0&&se[n][n]!=0) step+=2*p;
if(p!=0&&se[n][n]==0) continue;
if(step<=K)
res=max(res,l*w);
}
return res;
}
// BEGIN CUT HERE
// END CUT HERE
};
// BEGIN CUT HERE
450
DP ,LIS
和有意思的一道题目,题目的背景和DIV2的第一题相同,不同之处,是DIV1让我们判断能不能接到所有的坠落物,而这道题目则是问我们按照规则移动的条件下最多能够街道多少个物体。
我们社前后能够接到的球 分别为(x0,y0) (x1,y1)
我们知道这两个球的落点距离差为 | x1-x0 | ,同样这个差也代表了要消耗的单位时间。 然后我们可以用y坐标做差 y1-y0 这样我们就得到两个物体落地时间的差值,这个差值代表了从0到1最慢要花多少时间。
显然, 如果能够连续接到两个物体,那么 |x1-x0|<=y1-y0
去掉绝对值之后 y1-y0>=x1-x0 , y1-y0>=x0-x1
移项之后我们得到两个不等式 y1-x1>=y0-x0 , y1+x1>=y0+x0
对于所有坐标(x,y) 我们进行变换 设 s=y1-x1 d=y1+x1 得到 新的坐标(s,d)
然后对于新坐标的人一个变量排序再对另一个变量求LIS这个问题边转化成了一个DP问题。
这道题目处理LIS 需要用到LIS的nlogn算法,这个网上资料听得多的。
这道题目的转化很经典。
// BEGIN CUT HERE
// END CUT HERE
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <ctime>
#include <utility>
#include <iterator>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef set<int> si;
typedef map<int,int> mii;
typedef map<string,int> msi;
typedef pair<int,int> pii;
typedef priority_queue<int,vector<int>,greater<int> > pless;
typedef priority_queue<int> pgreater;
#define clr(x,a) memset(x,a,sizeof(x))
#define sz(x) (int)x.size()
#define pb push_back
#define mp make_pair
#define REP(i,n) for(i=0;i<(n);++i)
#define FOR(i,l,h) for(i=(l);i<=(h);++i)
#define FORD(i,h,l) for(i=(h);i>=(l);--i)
class CatchTheBeat
{
public:
int l[500100],len;
int binSearch(int L,int R,int v){
int m;
while(L<=R){
m=(L+R)>>1;
if(l[m]<=v)
L=m+1;
else
R=m-1;
}
//cout<<L<<endl;
return L;
}
int maxCatched(int n, int x0, int y0, int a, int b, int c, int d, int mod1, int mod2, int offset)
{
//题目里面有句话
//Watch out for integer overflow when generating the coordinates.
vector<ll> x(n),y(n);
x[0]=(ll)x0;
for(int i=1;i<n;i++)
x[i]=(x[i-1]*a+b)%(ll)mod1;
for(int i=0;i<n;i++)
x[i]=x[i]-offset;
y[0]=y0;
for(int i=1;i<n;i++)
y[i]=(y[i-1]*c+d)%(ll)mod2;
vector<pii> vp;
for(int i=0;i<n;i++)
if(y[i]>=0&&y[i]-x[i]>=0&&y[i]+x[i]>=0) //初始的点没加进去(0,0)
vp.pb(mp(y[i]-x[i],y[i]+x[i]));
sort(vp.begin(),vp.end());
//LIS
len=0,l[0]=0;
n=sz(vp);
for(int i=0;i<n;i++){
int pos=binSearch(0,len,vp[i].second);
if(pos>len){
l[pos]=vp[i].second;
len++;
}else if(pos!=0)
l[pos]=min(l[pos],vp[i].second);
}
return len;
}
// BEGIN CUT HERE
// END CUT HERE
};
// BEGIN CUT HERE
// END CUT HERE