08-18考试总结

唉,本来可以 AK 的

0818可爱精灵宝贝

  • 考验状态设计和预处理的区间 DP 题
  • 状态设计几乎和关路灯完全一样
  • 也是以人的位置,对状态分类
  • 分为人在左端点,人在右端点
  • 然鹅考试
  • 剩下的代码里有
/*************************************************************************
> File Name: Pokemon.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-18 15:52:02
>
************************************************************************/
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+7,M=1e2+7;
struct Node{
int pos,val;
int t;
}p[N];
int f[N][M][M][2];
int n,m,k;
int res=0;
int tlim;
int s;
bool cmp(Node a,Node b){
return a.pos<b.pos;
}
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
int main(){
//出屎化
memset(f,128,sizeof(f));
qread(n),qread(k),qread(m);
for(int i=1;i<=m;i++){
int a,b,t;
qread(a),qread(b),qread(t);
p[i]={a,b,t};
tlim=max(t,tlim);
}
//出屎节点
p[++m]={k,0,tlim};
sort(p+1,p+m+1,cmp);
for(int i=1;i<=m;i++) if(p[i].pos==k&&!p[i].val) s=i;
f[0][s][s][0]=f[0][s][s][1]=0;
//预处理左半部分
for(int i=s-1;i>;i--){
int now=abs(p[s].pos-p[i].pos),pre=abs(p[s].pos-p[i+1].pos);
f[now][i][s][0]=f[pre][i+1][s][0];
if(now<p[i].t) f[now][i][s][0]+=p[i].val;
res=max(res,f[now][i][s][0]);
}
//预处理右半部分
for(int i=s+1;i<=m;i++){
int now=abs(p[i].pos-p[s].pos),pre=abs(p[i-1].pos-p[s].pos);
f[now][s][i][1]=f[pre][s][i-1][1];
if(now<p[i].t) f[now][i][s][1]+=p[i].val;
res=max(res,f[now][s][i][1]);
}
//合并区间DP
for(int t=1;t<=tlim;t++)
for(int l=1;l<=s-1;l++)
for(int r=s+1;r<=m;r++){
int tback=abs(p[r].pos-p[l].pos),tl=abs(p[l+1].pos-p[l].pos),tr=abs(p[r].pos-p[r-1].pos);
f[t][l][r][0]=max(f[max(t-tl,0)][l+1][r][0],f[max(t-tback,0)][l+1][r][1])+((t<p[l].t)?p[l].val:0);
f[t][l][r][1]=max(f[max(t-tr,0)][l][r-1][1],f[max(t-tback,0)][l][r-1][0])+((t<p[r].t)?p[r].val:0);
res=max(res,max(f[t][l][r][0],f[t][l][r][1]));
}
printf("%d",res);
return 0;
}


0818最短路(path)

  • 思路还是比较简单的
  • 首先你以所有必经点(包括起点、终点)为原点,跑最短路
  • 求得两两必经点间的距离
  • 然后在必经点上跑爆搜,不会 T
/*************************************************************************
> File Name: shortestpath.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-18 17:37:26
>
************************************************************************/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+7,M=2e5+7;
int tot=0;
int n,m,s;
int head[N];
long long d[N];
bool v[N];
priority_queue<pair<long long,int> > q;
inline int redn(){
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline long long redl(){
long long ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
struct edge{
int ver,next;
long long len;
}e[M];
void add(int x,int y,long long z){
e[++tot].ver=y;
e[tot].len=z;
e[tot].next=head[x];
head[x]=tot;
}
int dist[13][13];
int S,T,k;
int p[14];
bool vis[14];
int ans=2147483647;
void dijkstra(int s,int id){
memset(v,0,sizeof(v));
for(register int i=1;i<=n;i++){
d[i]=2147483647;
}
d[s]=0;
q.push(make_pair(0,s));
while(!q.empty()){
int x=q.top().second;
q.pop();
if(v[x])
continue;
for(register int i=head[x];i;i=e[i].next){
int y=e[i].ver,z=e[i].len;
if(d[y]>d[x]+z){
d[y]=d[x]+z;
q.push(make_pair(-d[y],y));
v[x]=1;
}
}
}
for(int i=0;i<=k+1;i++){
if(i==id) continue;
dist[id][i]=d[p[i]];
}
}
vector<int> path;
void solve(int step){
if(step==k+1){
int res=0,fl=0;
path.push_back(k+1);
for(int i=1;i<k+2;i++){
if(dist[path[i-1]][path[i]]==2147483647){
fl=1;
break;
}
res+=dist[path[i-1]][path[i]];
}
path.clear();
if(fl) return;
else{
ans=min(ans,res);
return;
}
}
for(int i=1;i<=k;i++){
if(vis[i]) continue;
vis[i]=1;
path.push_back(i);
solve(step+1);
path.pop_back();
vis[i]=0;
}
}
signed main(){
scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&S,&T);
for(register int i=1;i<=m;i++){
int x,y;
long long z;
x=redn();
y=redn();
z=redl();
add(x,y,z);
}
for(int i=1;i<=k;i++) scanf("%lld",&p[i]);
p[0]=S,p[k+1]=T;
for(int i=0;i<=k+1;i++)
dijkstra(p[i],i);
path.push_back(0);
solve(1);
if(ans==2147483647) puts("-1");
else printf("%lld\n",ans);
return 0;
}


0818剑与魔法(dragons)

  • 首先对事件按返回事件分段
  • 求出每一段的限制数量,把这一段的塞进堆里,取出前几个
  • 记得最后一段特判,最后一个要求不必满足
/*************************************************************************
> File Name: SwordAndMagic.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-18 14:07:08
>
************************************************************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
char op[3];
ll ans;
ll n,t;
ll tot,idx;
priority_queue<ll,vector<ll>,greater<ll> > q;
signed main(){
qread(n);
for(int i=1;i<=n;i++){
scanf("%s",op);
qread(t);
if(i==n){
tot=t;
break;
}
if(*op=='c') q.push(t);
else while(q.size()>=t) q.pop();
}
while(!q.empty()) ans+=q.top(),q.pop(),idx++;
if(idx<tot) puts("-1");
else printf("%lld\n",ans);
return 0;
}


0818三角形(triangle)

  • 在插入点的同时,考虑新增的三角形
  • 首先插入新增的线,按斜率排序
  • 然后 总 \(-\) 不和法 得到合法的
  • 不合法的就是斜率相同的组成的那些
/*************************************************************************
> File Name: CountingTrangles.cpp
> Author: Typedef
> Mail: 1815979752@qq.com
> Created Time: 2021-08-18 15:05:03
>
************************************************************************/
#include<bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
const int N=2e6+7;
ll x[N],y[N];
double k[N];
template<class T>void qread(T &x){
x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f) x=-x;
}
ll cnt,idx;
ll res=0;
ll n;
double get_k(ll X1,ll Y1,ll X2,ll Y2){
return (1.0*(double)(Y1-Y2))/(1.0*(double)(X1-X2));
}
int main(){
qread(n);
for(int i=1;i<=n;i++){
qread(x[i]),qread(y[i]);
idx=0;
for(int j=i-1;j;j--){
if(x[i]==x[j]) k[++idx]=INF;
else k[++idx]=get_k(x[i],y[i],x[j],y[j]);
}
sort(k+1,k+idx+1);
cnt=1;
for(int j=2;j<=idx;j++){
if(k[j]==k[j-1]) cnt++;
else res+=cnt*(cnt-1)>>1,cnt=1;
}
res+=cnt*(cnt-1)>>1;
}
printf("%lld\n",n*(n-1)*(n-2)/6-res);
return 0;
}