过路费
原题 CodeForces gym 101630 J 。
经典的错算例子。
如果我们只支付
≥
m
i
d
\ge mid
≥mid边的费用,那么
<
m
i
d
<mid
<mid的边边权是
0
0
0,可以随便经过。
因此我们枚举边权,把
w
w
w改为
max
(
0
,
w
−
m
i
d
)
\max(0,w-mid)
max(0,w−mid),然后跑最短路,答案是
d
i
s
[
n
]
+
k
∗
m
i
d
dis[n]+k*mid
dis[n]+k∗mid
如果经过的
≥
m
i
d
\ge mid
≥mid的边超过
k
k
k的话,那么算出来比答案大,原因在于对
>
k
>k
>k条边支付了费用。
如果经过的
≥
m
i
d
\ge mid
≥mid的边不足
k
k
k的话,那么算出来还是比答案大
因此如果对答案有贡献,那么经过的
≥
m
i
d
\ge mid
≥mid的边一定恰好是
k
k
k条
如果本身经过的边就不足
k
k
k条,那么让
m
i
d
=
0
mid=0
mid=0即可。
搞破坏
原题 [APIO2017] 斑斓之地
平面图中的欧拉定理:
设G为任意的联通平面图,则v-e+f=2,v是G的顶点数,e是G的边数,f是G的面数。
可以简单理解为,首先建一棵树,然后每新增一条边,就会多分割出一个平面。
对于每两块相邻的可用格子,连一条边,形成一个图G。题目就是问矩形区域内导出子图中连通块个数。
网格图显然是平面图。因此v-e+f=连通块数+1。
e就是1x2格子的个数,f就是2x2格子的个数+1,v就是1x1格子的个数。可以假想刚开始所有格子都是可用的,然后删掉一个格子后的变化,可以二维数点解决。
注意如果询问的矩形区域包含怪兽经过的所有格子,那么怪兽经过的所有格子的外围一圈格子会形成一个新的面,特判即可。
复杂度
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
似乎t3,t4不难,但是我是丝薄。我只会打暴力。
感觉效率好低啊
其实写博客也算一种放松吧
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define pb push_back
#define db double
#define mp make_pair
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
int R,C,n,m,X,Y;
int X3,X4,Y3,Y4;
int bit[200005][5];
ll res[100005];
map<pair<int,int>,int>id;
struct node{
int x,type,id,val;
};
struct node2{
int x,type;
};
vector<node>v[200005];
vector<node2>g[200005];
string s;
void add(int x,int y,int type){
if(!x||!y)return;
g[x].pb({y,type});
}
void Add(int x,int y,int type,int id,int val){
if(!x||!y)return;
v[x].pb({y,type,id,val});
}
void add2(int X,int Y,int X2,int Y2,int type,int id,int val){
if(X>X2||Y>Y2)return;
Add(X2,Y2,type,id,val),Add(X-1,Y2,type,id,-val),Add(X2,Y-1,type,id,-val),Add(X-1,Y-1,type,id,val);
}
int V(int x,int y){
return id.find(mp(x,y))==id.end();
}
void del(int x,int y){
if(!V(x,y))return;
add(x,y,1);
if(V(x,y+1))add(x,y,2);
if(V(x,y-1))add(x,y-1,2);
if(V(x+1,y))add(x,y,3);
if(V(x-1,y))add(x-1,y,3);
if(V(x-1,y-1)&&V(x-1,y)&&V(x,y-1)&&V(x,y))add(x-1,y-1,4);
if(V(x-1,y)&&V(x-1,y+1)&&V(x,y)&&V(x,y+1))add(x-1,y,4);
if(V(x,y)&&V(x,y+1)&&V(x+1,y)&&V(x+1,y+1))add(x,y,4);
if(V(x,y-1)&&V(x,y)&&V(x+1,y-1)&&V(x+1,y))add(x,y-1,4);
id[mp(x,y)]=1;
}
void upd(int x,int type,int z){for(;x<=C;x+=x&-x)bit[x][type]+=z;}
int ask(int x,int type){int tot(0);for(;x;x-=x&-x)tot+=bit[x][type];return tot;}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>R>>C>>n>>m>>X>>Y;del(X,Y);if(n)cin>>s;X3=X4=X,Y3=Y4=Y;
for(int i=0;i<n;i++){
if(s[i]=='N')X--;else if(s[i]=='S')X++;
else if(s[i]=='W')Y--;else Y++;
X3=min(X3,X),X4=max(X4,X),Y3=min(Y3,Y),Y4=max(Y4,Y);
del(X,Y);
}
for(int i=1;i<=m;i++){
int X,Y,X2,Y2;
cin>>X>>Y>>X2>>Y2;
if(X<X3&&X4<X2&&Y<Y3&&Y4<Y2)res[i]++;
add2(X,Y,X2,Y2,1,i,-1),add2(X,Y,X2,Y2-1,2,i,1),add2(X,Y,X2-1,Y2,3,i,1),add2(X,Y,X2-1,Y2-1,4,i,-1);
}for(int i=1;i<=R;i++){
for(auto x:g[i])upd(x.x,x.type,1);
for(auto x:v[i]){
res[x.id]+=x.val*ask(x.x,x.type);
}
}for(int i=1;i<=m;i++){
cout<<res[i]+1<<"\n";
}
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2021-11-18 【题解】Matrix