Codeforces Round #766 (Div. 2)思路整理
灵感当然可以用来做题,但迟早会有灵感枯竭的一天。
Codeforces Round #766 (Div. 2)
A. Not Shading
答案只可能为0,-1,1,2,分情况讨论即可。
B. Not Sitting
可以发现一个比较显然的性质,最后Tina的座位一定是四个角是最优的。那么考虑Rahul的话,就是每个点的代价就是当前这个点到四个角的距离取max.这样再把所有的点从小到大排序,就是Rahul依次会坐的点。
C. Not Assigning
这个构造就比较有意思(我一直都觉得cf的构造题真的很有意思。)
可以发现由于每个数都是质数,考虑一个有三个出度的点,那么这三个边至少有两个是奇数,(另外一个质数可以是2)。那么这两个奇数相加就是偶数,不符合题意。所以每个点的出边最多是2.考虑这样的树只能是一条链,所以直接特判链的情况,然后可以按照2,3,2,3...这样赋值即可。
D. Not Adding
这个题当初真的是卡了很久....可以发现n和ai的范围都是1e6的级别,正常思路都是先考虑用n的数量级来做,考虑两两之间的操作呀什么的。可怎么样都想不到后,可以从值域的角度思考,发现ai的数据也为1e6,那么我们可以枚举每一个数来判断这个数能不能被添加,这个数能被添加的条件是这个数能是两个数(或多个数)的gcd,换言之,这个数的几个倍数,之间除掉这个数后,剩下的数互质。那么这样我们就可以做了,枚举一下每一个数,之后枚举这个数的倍数,考虑这些倍数之间除掉这个数后是否互质即可。
E. Not Escaping
spfa已经死了,比赛的时候打了spfa,然后由于一点小失误没调出来,之后再交,果然T了,果然不能相信spfa.....
发现这个图建出来后层与层之间是单向的边,完全可以用DP,然后单独考虑某一层时,由于是左右线性的,我完全可以从左到右然后从右到左,做两次DP即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
int n,m,k,T,num,w[N],b[N];
ll f[N*2];
map<pair<int,int>,int>id;
map<int,bool>fs[N];
vector<int>v[N];
vector<pair<int,int> >vs[N*2];
inline void clear()
{
id.clear();
for(int i=1;i<=n;++i) fs[i].clear(),v[i].clear();
for(int i=1;i<=num;++i) vs[i].clear();
num=0;
}
int main()
{
// freopen("1.in","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
clear();
for(int i=1;i<=n;++i) scanf("%d",&w[i]);
id[{1,1}]=++num;id[{n,m}]=++num;
fs[1][1]=1;fs[n][m]=1;
v[1].push_back(1);
v[n].push_back(m);
for(int i=1;i<=k;++i)
{
int a,b,c,d,h;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&h);
if(id.find({a,b})==id.end()) id[{a,b}]=++num;
if(id.find({c,d})==id.end()) id[{c,d}]=++num;
vs[id[{a,b}]].push_back({id[{c,d}],h});
if(fs[a].find(b)==fs[a].end())
{
v[a].push_back(b);
fs[a][b]=1;
}
if(fs[c].find(d)==fs[c].end())
{
v[c].push_back(d);
fs[c][d]=1;
}
}
for(int i=1;i<=num;++i) f[i]=0xefefefefefefefef;
f[1]=0;
for(int i=1;i<=n;++i)
{
sort(v[i].begin(),v[i].end());
int tot=0;
for(int j=0;j<v[i].size();++j) b[++tot]=id[{i,v[i][j]}];
for(int j=1;j<tot;++j)
f[b[j+1]]=max(f[b[j+1]],f[b[j]]-(ll)w[i]*abs(v[i][j]-v[i][j-1]));
for(int j=tot;j>1;--j)
f[b[j-1]]=max(f[b[j-1]],f[b[j]]-(ll)w[i]*abs(v[i][j-1]-v[i][j-2]));
for(int j=1;j<=tot;++j)
for(auto y:vs[b[j]])
f[y.first]=max(f[y.first],f[b[j]]+y.second);
}
if(f[2]<-1e18) puts("NO ESCAPE");
else printf("%lld\n",-f[2]);
}
return 0;
}