A.凸多边形曼哈顿
题意:给你一个凸多边形,问你当其中K边形的最大dis[]是多少?
思路:首先是要发现K>=4的时候答案就是定值,然后再讨论k=3,暴力找四个最远点和剩下点构成三角形。
/*
▄███████▀▀▀▀▀▀███████▄
░▐████▀▒▒▒▒▒▒▒▒▒▒▀██████▄
░███▀▒▒▒ACCEPTED▒▒▒▒▀█████
░▐██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░▐█▌▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░░█▒▄▀▀▀▀▀▄▒▒▄▀▀▀▀▀▄▒▐███▌
░░░▐░░░▄▄░░▌▐░░░▄▄░░▌▐███▌
░▄▀▌░░░▀▀░░▌▐░░░▀▀░░▌▒▀▒█▌
░▌▒▀▄░░░░▄▀▒▒▀▄░░░▄▀▒▒▄▀▒▌
░▀▄▐▒▀▀▀▀▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒█
░░░▀▌▒▄██▄▄▄▄████▄▒▒▒▒█▀
░░░░▄██████████████▒▒▐▌
░░░▀███▀▀████▀█████▀▒▌
░░░░░▌▒▒▒▄▒▒▒▄▒▒▒▒▒▒▐
░░░░░▌▒▒▒▒▀▀▀▒▒▒▒▒▒▒▐
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5;
const int INF=1e9+7;
const double eps=1e-6;
const int mod=1e9+7;
typedef long long ll;
typedef pair<ll,ll>p;
int x[N],y[N];
int n,a[N],ans[N];
int judge(int i,int j,int k)
{
int sum=0;
sum+=abs(x[i]-x[j])+abs(y[i]-y[j]);
sum+=abs(x[i]-x[k])+abs(y[i]-y[k]);
sum+=abs(x[k]-x[j])+abs(y[k]-y[j]);
return sum;
}
int main() {
int bigy=-INF,bigx=-INF,smallx=INF,smally=INF;
cin>>n;
for(int i=1; i<=n; i++) {
scanf("%d%d",&x[i],&y[i]);
bigy=max(bigy,y[i]);
bigx=max(bigx,x[i]);
smally=min(smally,y[i]);
smallx=min(smallx,x[i]);
}
for(int i=4; i<=n; i++) {
ans[i]=(bigx-smallx+bigy-smally)*2;
}
int now=0;
for(int i=1; i<=n; i++) {
if(x[i]==bigx)
a[++now]=i;
if(x[i]==smallx)
a[++now]=i;
if(y[i]==bigy)
a[++now]=i;
if(y[i]==smally)
a[++now]=i;
}
sort(a+1,a+now+1);
now=unique(a+1,a+now+1)-a-1;
do {
int sum=0;
for(int i=1; i<=2; i++) {
sum+=abs(x[a[i]]-x[a[i+1]])+abs(y[a[i]]-y[a[i+1]]);
}
sum+=abs(x[a[3]]-x[a[1]])+abs(y[a[3]]-y[a[1]]);
ans[3]=max(ans[3],sum);
} while(next_permutation(a+1,a+now+1));
for(int i=1; i<=now; i++) {
for(int j=i+1; j<=now; j++) {
for(int k=1; k<=n; k++) {
int id1=a[i],id2=a[j],id3=k;
if(id1==id2||id1==id3||id2==id3)
continue;
ans[3]=max(judge(id1,id2,id3),ans[3]);
}
}
}
for(int i=3; i<=n; i++) {
printf("%d%c",ans[i],i==n?'\n':' ');
}
}
E.矩阵快速幂
题意:求S = 2{m-1}×A+2{m-2}×A2+……+2{m-m}×A^m
思路:跟训练赛那题差不多,当时训练赛没过,后来也看题解了,但还是没思考为什么要那样构造矩阵,这次有点可惜,满足项之间的递推关系就能矩阵快速幂。
注意:矩阵2是2E,不是全2
/*
▄███████▀▀▀▀▀▀███████▄
░▐████▀▒▒▒▒▒▒▒▒▒▒▀██████▄
░███▀▒▒▒ACCEPTED▒▒▒▒▀█████
░▐██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░▐█▌▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░░█▒▄▀▀▀▀▀▄▒▒▄▀▀▀▀▀▄▒▐███▌
░░░▐░░░▄▄░░▌▐░░░▄▄░░▌▐███▌
░▄▀▌░░░▀▀░░▌▐░░░▀▀░░▌▒▀▒█▌
░▌▒▀▄░░░░▄▀▒▒▀▄░░░▄▀▒▒▄▀▒▌
░▀▄▐▒▀▀▀▀▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒█
░░░▀▌▒▄██▄▄▄▄████▄▒▒▒▒█▀
░░░░▄██████████████▒▒▐▌
░░░▀███▀▀████▀█████▀▒▌
░░░░░▌▒▒▒▄▒▒▒▄▒▒▒▒▒▒▐
░░░░░▌▒▒▒▒▀▀▀▒▒▒▒▒▒▒▐
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 60 + 5;
const int INF=1e9+7;
const double eps=1e-6;
const long long mod=1e9+7;
typedef long long ll;
typedef pair<ll,ll>p;
ll x[N],y[N];
ll n,a[N][N],ans[N],m;
struct mat {
ll mp[N][N];
mat() {
memset(mp,0,sizeof mp);
}
};
mat A;
mat mul(mat A,mat B) {
mat ans;
for(ll i=1; i<=n*2; i++) {
for(ll j=1; j<=n*2; j++) {
for(ll k=1; k<=n*2; k++) {
ans.mp[i][j]=(ans.mp[i][j]%mod+A.mp[i][k]*B.mp[k][j]%mod)%mod;
}
}
}
return ans;
}
mat Pow(mat base,ll b) {
mat ans;
for(ll i=1; i<=n*2; i++) {
ans.mp[i][i]=1;
}
while(b) {
// cout<<" b= "<<b<<endl;
if(b&1) {
ans=mul(ans,base);
}
base=mul(base,base);
b>>=1;
}
return ans;
}
int main() {
scanf("%lld%lld",&n,&m);
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
scanf("%lld",&a[i][j]);
}
}
mat base;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
base.mp[i][j]=base.mp[i][j+n]=a[i][j];
if(i==j)
base.mp[i+n][j+n]=2;
}
}
mat ans;
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
ans.mp[i][j]=a[i][j];
}
}
for(int i=n+1; i<=n+n; i++) {
for(int j=1; j<=n; j++) {
if(i-n==j)
ans.mp[i][j]=2;
}
}
mat tmp=Pow(base,m-1);
// printf("show tmp\n");
// for(int i=1; i<=n+n; i++) {
// for(int j=1; j<=n+n; j++) {
// printf("%lld%c",tmp.mp[i][j]," \n"[j==n+n]);
// }
// }
ans=mul(tmp,ans);
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
printf("%lld%c",ans.mp[i][j]," \n"[j==n]);
}
}
}
/*
1 3
1
*/
I.线段dp
题意:略。
思路:这题主要是明白为什么dp要逆推,首先我们能玩就玩的思想,可以看出来前面选还是不选会影响到后面,有后效性问题,我们假如从后往前更新就不会产生该问题,题解感觉说的很明白:
根据 dp 要求什么就设什么的伟大思想。我们直接设 dp[i]表示从 i 时刻到 n+1 时刻的空闲时间。
1.如果此时没有游戏可以玩那么 dp[i]=dp[i+1]+1 是显然的。
2.如果此时有游戏可以玩那么dp[i]=max(dp[此游戏的结束时间],dp[i])。
/*
▄███████▀▀▀▀▀▀███████▄
░▐████▀▒▒▒▒▒▒▒▒▒▒▀██████▄
░███▀▒▒▒ACCEPTED▒▒▒▒▀█████
░▐██▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░▐█▌▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▌
░░█▒▄▀▀▀▀▀▄▒▒▄▀▀▀▀▀▄▒▐███▌
░░░▐░░░▄▄░░▌▐░░░▄▄░░▌▐███▌
░▄▀▌░░░▀▀░░▌▐░░░▀▀░░▌▒▀▒█▌
░▌▒▀▄░░░░▄▀▒▒▀▄░░░▄▀▒▒▄▀▒▌
░▀▄▐▒▀▀▀▀▒▒▒▒▒▒▀▀▀▒▒▒▒▒▒█
░░░▀▌▒▄██▄▄▄▄████▄▒▒▒▒█▀
░░░░▄██████████████▒▒▐▌
░░░▀███▀▀████▀█████▀▒▌
░░░░░▌▒▒▒▄▒▒▒▄▒▒▒▒▒▒▐
░░░░░▌▒▒▒▒▀▀▀▒▒▒▒▒▒▒▐
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int INF=1e9+7;
const double eps=1e-6;
const long long mod=1e9+7;
typedef long long ll;
typedef pair<ll,ll>p;
int dpmin[N],dpmax[N],cnt[N];
struct node {
int l,r;
bool operator<(const node &a)const {
if(a.l!=l)
return a.l<l;
return a.r<r;
}
}a[N];
int up,n;
int main() {
scanf("%d%d",&up,&n);
for(int i=1; i<=n; i++) {
scanf("%d%d",&a[i].l,&a[i].r);
cnt[a[i].l]++;
}
sort(a+1,a+n+1);
int now=0;
for(int i=up; i>=1; i--) {
if(cnt[i]==0) {
dpmin[i]=dpmin[i+1]+1;
dpmax[i]=dpmax[i+1]+1;
} else {
dpmin[i]=dpmin[a[++now].r];
dpmax[i]=dpmax[a[now].r];
for(int j=1; j<cnt[i]; j++) {
dpmin[i]=min(dpmin[i],dpmin[a[++now].r]);
dpmax[i]=max(dpmax[i],dpmax[a[now].r]);
}
}
}
cout<<dpmin[1]*4+dpmax[1]*3<<endl;
//cout<<dpmin[1]<<" "<<dpmax[1]<<endl;
}