暴力模拟即可
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define put(x) putchar(x)
#define eoln put('\n')
#define space put(' ')
inline int read(){
int x=0,neg=1;char c=getchar();
while(!isdigit(c)){
if(c=='-') neg=-1;
c=getchar();
}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x*neg;
}
inline void print(int x){
if(x<0){
putchar('-');
print(abs(x));
return;
}
if(x<=9) putchar(x+'0');
else{
print(x/10);
putchar(x%10+'0');
}
}
int n=read(),q=read();
multiset<int> st;
int cnt=0;
bool vis[3][100005];
int main(){
while(q--){
int a=read(),b=read();
a--;
vis[a][b]=vis[a][b]^1;
if(vis[a][b]){
if(vis[a^1][b-1]) cnt++;
if(vis[a^1][b]) cnt++;
if(vis[a^1][b+1]) cnt++;
}
else{
if(vis[a^1][b-1]==1) cnt--;
if(vis[a^1][b]==1) cnt--;
if(vis[a^1][b+1]==1) cnt--;
}
// cout<<cnt<<endl;
if(cnt) puts("No");
else puts("Yes");
}
return 0;
}
这题由于自然溢出FST了,现在心情很是蓝瘦
我们可以把所有横纵坐标 ≤ 4 × 1 0 16 \leq 4 \times 10^{16} ≤4×1016 的点全部求出来,这样的点不超过 64 64 64 个。然后我们枚举一个点作为出发点,然后不断地向左下/右上方向跑,跑到头再拐弯往回跑,直到 t = 0 t=0 t=0 为止并更新答案。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define put(x) putchar(x)
#define eoln put('\n')
#define space put(' ')
#define int long long
inline int read(){
int x=0,neg=1;char c=getchar();
while(!isdigit(c)){
if(c=='-') neg=-1;
c=getchar();
}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x*neg;
}
inline void print(int x){
if(x<0){
putchar('-');
print(abs(x));
return;
}
if(x<=9) putchar(x+'0');
else{
print(x/10);
putchar(x%10+'0');
}
}
int x[105],y[105];
int ax,ay,bx,by;
int sx,sy,t,cntx,cnty,ans=0;
int dist(int i,int j){
return abs(x[j]-x[i])+abs(y[j]-y[i]);
}
signed main(){
cin>>x[0]>>y[0]>>ax>>ay>>bx>>by>>sx>>sy>>t;
for(cntx=1;x[cntx-1]<=4e16;++cntx)
x[cntx]=ax*x[cntx-1]+bx;
for(cnty=1;y[cnty-1]<=4e16;++cnty)
y[cnty]=ay*y[cnty-1]+by;
for(int i=0;i<cntx&&i<cnty;i++){
int sum=abs(sx-x[i])+abs(sy-y[i]);
if(sum>t) continue;
for(int j=i-1;j>=0;j--){
sum+=dist(j+1,j);
if(sum>t){
ans=max(ans,i-j);
break;
}
}
if(sum>t) continue;
int p=0;
for(int j=i+1;;j++){
sum+=dist(j,p);
if(sum>t){
ans=max(ans,j);
break;
}
p=j;
}
}
cout<<ans<<endl;
}
我们不难发现,要向使得答案最优,确定 0 0 0 以后,必须让 1 1 1 和 0 0 0 相邻, 2 2 2 与 0 , 1 0,1 0,1 组成一条链……
因此我们考虑从小到大放这些数。 d p x , y dp_{x,y} dpx,y 表示在从 x x x 到 y y y 的链上填上 0 0 0 至 l e n − 1 len-1 len−1 的数的最优解。那么我们枚举新加进来的一条边,只有 2 2 2种可能(与 x x x 相邻并且在链上的边,和与 y y y 相邻并且在链上的边)假设为 ( x , s ) (x,s) (x,s) 和 ( t , y ) (t,y) (t,y),然后更新 d p x , y = m a x ( d p u , y + d p x , v ) + s z [ x ] ∗ s z [ y ] dp_{x,y}=max(dp_{u,y}+dp_{x,v})+sz[x]*sz[y] dpx,y=max(dpu,y+dpx,v)+sz[x]∗sz[y],其中 s z sz sz 为子树大小。最终答案就是 max i = 1 n max j = 1 n d p i , j \max_{i=1}^n \max_{j=1}^n dp_{i,j} maxi=1nmaxj=1ndpi,j。由于搜索顺序不确定,需要记忆化搜索。
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define put(x) putchar(x)
#define eoln put('\n')
#define space put(' ')
#define int long long
inline int read(){
int x=0,neg=1;char c=getchar();
while(!isdigit(c)){
if(c=='-') neg=-1;
c=getchar();
}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x*neg;
}
inline void print(int x){
if(x<0){
putchar('-');
print(abs(x));
return;
}
if(x<=9) putchar(x+'0');
else{
print(x/10);
putchar(x%10+'0');
}
}
int n=read();
vector<int> g[3005];
int fa[3005],dep[3005],sz[3005];
inline void dfs(int x){
sz[x]=1;
for(int i=0;i<g[x].size();i++){
int y=g[x][i];
if(y==fa[x]) continue;
fa[y]=x;
dep[y]=dep[x]+1;
dfs(y);
sz[x]+=sz[y];
}
}
int fa0[3005][3005];
int f[3005][3005];
inline int dump(int x,int y){
if(~f[x][y])
return f[x][y];
return f[x][y]=max(dump(fa[x],y),dump(x,fa[y]))+sz[x]*sz[y];
}
signed main(){
for(int i=1;i<n;i++){
int x=read(),y=read();
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1);
memset(f,-1,sizeof(f));
for(int i=1;i<=n;i++){
int x=i,now=0;
fa0[i][0]=i;
while(x=fa[x])
fa0[i][++now]=x;
}
for(int i=1;i<=n;i++)
f[i][i]=0;
for(int j=1;j<=n;j++)
for(int i=1;i<=n;i++)
if(fa0[i][j])
f[i][fa0[i][j]]=f[fa0[i][j]][i]=max(f[fa[i]][fa0[i][j]],f[i][fa0[i][j-1]])+sz[i]*(sz[1]-sz[fa0[i][j-1]]);
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ans=max(ans,dump(i,j));
cout<<ans<<endl;
return 0;
}