0%

当年用python写的代码

193.18pts TLE 3/22 WA 2/22

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=70565258

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from collections import deque

# 输入
y_, x_ = map(int, input().split())
maze = [list(input()) for _ in range(y_)]

# 各个方向都能走 不能走上 不能走下 不能走左 不能走右
qList = [(0, 0, 0, 4, 1), (0, 0, 0, 3, 1), (0, 0, 0, 2, 1), (0, 0, 0, 1, 1), (0, 0, 0, 0, 1)] # x, y, d, 健全, 穿墙次数
direction5 = [[(-1, 0), (0, 1), (0, -1)], [(1, 0), (0, 1), (0, -1)], [(1, 0), (-1, 0), (0, 1)],
[(1, 0), (-1, 0), (0, -1)], [(1, 0), (-1, 0), (0, 1), (0, -1)]]

def bfs():
visited = [[[False] * 2 for _ in range(x_)] for _ in range(y_)]
q = deque(qList)
while q:
x0, y0, d, dI, throughAb = q.popleft()
if visited[y0][x0][throughAb]:
continue
visited[y0][x0][throughAb] = True

for dx, dy in direction5[dI]:
nx, ny = x0 + dx, y0 + dy
if 0 <= nx < x_ and 0 <= ny < y_:
# 终点判断
if nx == x_ - 1 and ny == y_ - 1:
if maze[ny][nx] == '.' or (maze[ny][nx] == 'X' and throughAb == 1):
return d + 1

# 走路与穿墙判断
if maze[ny][nx] == '.' and not visited[ny][nx][throughAb]:
q.append((nx, ny, d + 1, dI, throughAb))
elif maze[ny][nx] == 'X' and throughAb == 1 and not visited[ny][nx][0]:
q.append((nx, ny, d + 1, dI, 0))

return -1

print(bfs())

60pts TLE 可能是check函数复杂度太高了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;
typedef long long ll;
const ll maxn=1e5+10,maxans=1e13+7;
ll n,m,a[maxn];
inline bool check(ll x) {
ll s=1,subCnt=0;
while (s<=n) {
ll res=0,cnt=0;
for(ll i=s;i<=n;i++) {
if(res+a[i]>x)
break;
res+=a[i];
cnt+=1;
}
s+=cnt;
subCnt+=1;
}
if(subCnt<=m) {
return true;
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
ll l=1,r=maxans;
while(l<r) {
ll mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
return 0;
}
// 60pts https://www.luogu.com.cn/record/180491211

可以二分里套二分,当然那个二分我们就不写了,直接上stl

P1182_2.in

P1182_2.out

不过我仔细分析了一下时间复杂度,以及这个样例(另一道题目https://www.luogu.com.cn/problem/P2884)

1
2
3
4
5
6
7
8
7 5
100
400
300
100
500
101
400
1
500

会使上面这个程序死循环,让我确信不是check()的问题

仔细分析过后,发现还是check()的问题,check死循环了。

1
2
3
4
5
6
7
8
9
10
11
while (s<=n) {
ll res=0,cnt=0;
for(ll i=s;i<=n;i++) {
if(res+a[i]>x) // 某些情况下,cnt走不到cnt+1,导致s停滞不前,导致死循环
break;
res+=a[i];
cnt+=1;
}
s+=cnt;
subCnt+=1;
}

解决起来倒也简单

ll l=maxa,r=maxans;

让左端点比数组中最大的元素大,就可以了,这样可以保证cnt的前进。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// https://www.luogu.com.cn/problem/P2884
// https://www.luogu.com.cn/problem/P1182 双倍经验
#include <iostream>
using namespace std;
typedef long long ll;
const ll maxn=1e5+10,maxans=1e13+7;
ll n,m,a[maxn];
inline bool check(ll x) {
ll s=1,subCnt=0;
while (s<=n) {
ll res=0,cnt=0;
for(ll i=s;i<=n;i++) {
if(res+a[i]>x)
break;
res+=a[i];
cnt+=1;
}
s+=cnt;
subCnt+=1;
}
if(subCnt<=m) {
return true;
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
ll maxa=0;
for(int i=1;i<=n;i++) {
cin>>a[i],maxa=max(maxa,a[i]);
}
ll l=maxa,r=maxans;
while(l<r) {
ll mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
return 0;
}
// 60pts TLE https://www.luogu.com.cn/record/180491211
// 40pts TLE https://www.luogu.com.cn/record/180498527
// AC https://www.luogu.com.cn/record/180509878
// AC https://www.luogu.com.cn/record/180510298

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// https://www.acwing.com/problem/content/791/
#include <iostream>
using namespace std;
const int maxn=100007;
int n,q,k,a[maxn];

int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
for(int _=1;_<=q;_++) {
cin>>k;
int l=1,r=n;
while (l<r) {
int mid=l+r>>1;
if(a[mid]>=k) r=mid;
else l=mid+1;
}
if(a[l]!=k) {
cout<<"-1 -1"<<endl;
continue;
}
int l2=1,r2=n;
while (l2<r2) {
int mid=l2+r2+1>>1;
if(a[mid]<=k) l2=mid;
else r2=mid-1;
}
cout<<l-1<<" "<<l2-1<<endl;
}
return 0;
}
// AC https://www.acwing.com/problem/content/submission/code_detail/37312161/


题目大意

给定 n 条线段,每条线段有两个端点坐标。移动时分为两种速度:移动到某条线段的起点/终点使用速度 s,沿着线段绘制使用速度 t。需要选择绘制线段的顺序及每条线段从哪一端开始,求完成全部绘制的最短总时间。

Pass 10/74 WA https://atcoder.jp/contests/abc374/submissions/58484468 赛时代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <bitset>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <deque>
using namespace std;
int n,s,t,pos[10][6]; // s->not emitting laser && t-> emitting ......
bool vis[10][6],vis2[10];
double ans=10000000,dis;
void dfs(int x,int y,int cnt){
if(cnt>=n){
ans=min(dis,ans);
return;
}
for(int i=1;i<=n;i++){
if(vis2[i]) continue;
vis2[i]=true;
double squareS1=(pos[i][3]-pos[i][1])*(pos[i][3]-pos[i][1]);
double squareS2=(pos[i][4]-pos[i][2])*(pos[i][4]-pos[i][2]);
double lenSeg=sqrt(squareS1+squareS2)/t;
for(int j=1;j<=3;j+=2){
double square1=(pos[i][j]-pos[x][y])*(pos[i][j]-pos[x][y]);
double square2=(pos[i][j+1]-pos[x][y+1])*(pos[i][j+1]-pos[x][y+1]);
double ldis=sqrt(square1+square2)/s;
dis=dis+(ldis+lenSeg);
dfs(i,j,cnt+1);
dis=dis-(ldis+lenSeg);
}
vis2[i]=false;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>s>>t;
for(int i=1;i<=n;i++){
cin>>pos[i][1]>>pos[i][2]>>pos[i][3]>>pos[i][4];
}
dis=0;
dfs(0,0,0);
cout<<ans<<endl;
//cin>>n;
}
// WA https://atcoder.jp/contests/abc374/submissions/58484468

只改了一个地方就AC了
dfs(i,4-j,cnt+1); // 进入点和终止点不是一个,这条线段的终止点就是下一条线段的起始点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <bitset>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <deque>
using namespace std;
int n,s,t,pos[10][6]; // s->not emitting laser && t-> emitting ......
bool vis[10][6],vis2[10];
double ans=10000000,dis;
void dfs(int x,int y,int cnt){
if(cnt>=n){
ans=min(dis,ans);
return;
}
for(int i=1;i<=n;i++){
if(vis2[i]) continue;
vis2[i]=true;
double squareS1=(pos[i][3]-pos[i][1])*(pos[i][3]-pos[i][1]);
double squareS2=(pos[i][4]-pos[i][2])*(pos[i][4]-pos[i][2]);
double lenSeg=sqrt(squareS1+squareS2)/t;
for(int j=1;j<=3;j+=2){
double square1=(pos[i][j]-pos[x][y])*(pos[i][j]-pos[x][y]);
double square2=(pos[i][j+1]-pos[x][y+1])*(pos[i][j+1]-pos[x][y+1]);
double ldis=sqrt(square1+square2)/s;
dis=dis+(ldis+lenSeg);
dfs(i,4-j,cnt+1); // 进入点和终止点不是一个,这条线段的终止点就是下一条线段的起始点
dis=dis-(ldis+lenSeg);
}
vis2[i]=false;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>s>>t;
for(int i=1;i<=n;i++){
cin>>pos[i][1]>>pos[i][2]>>pos[i][3]>>pos[i][4];
}
dis=0;
dfs(0,0,0);
cout.precision(17); // 打印double全精度
cout<<ans<<endl;
//cin>>n;
}
//AC https://atcoder.jp/contests/abc374/submissions/58506793
//AC https://www.luogu.com.cn/record/180435741

题目大意

给定一个数组,通过若干次“除以 2 取整”的操作把元素压到一定范围内,要求最终能覆盖 0 到 x-1 的所有数(每个数至少出现一次),求最大的可行 x。通常用二分答案 + 贪心检查。

AC 代码 二分答案 相比于那个过了93.33%的还是修改了很多。

总体的check函数的贪心思路是 ≥x 的没用,之前就到过的(vis中有的)也没用。

没用,那怎么让他有用那?那当然是>>1才有用,不断的>>1,直到有用(注意条件,不要死循环了)。

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71786526

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=1e5+7,maxA=static_cast<int>(1e6)+7;
int n,t,a[maxA],A;
set<int> vis;
inline bool check(int x) {
for(int i=n;i>=1;i--) {
int ai=a[i];
while(ai>=x)
ai>>=1;
while(vis.count(ai)!=0 && ai!=0) // 到过以前到过的值不算有用 ai!=0防止死循环的发生
ai>>=1;
vis.insert(ai);
}
for(int i=0;i<=x-1;i++) {
if(vis.count(i)==0)
return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
for(int _=1;_<=t;_++) {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
sort(&a[1],&a[n+1],less<int>());
int l=0,r=n+1; // 如果n个数连续,那么就是n
while(l<r) {
vis.clear();
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}
// TLE https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785349
// 53.33% WA https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785676
// 93.33% WA https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785979
// AC https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71786526

TLE pass 2/30

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;
const int maxn=1e5+7,maxA=static_cast<int>(1e6)+7;
int n,t,a[maxA],A;
bitset<maxA> ovis,vis;
inline bool check(int x) {
for(int i=n;i>=1;i--) {
int ai=a[i];
if(ai<x)
break;
while(ai>>=1) {
if(!vis[ai] && ai<x) {vis[ai]=true;break;}
}
}
for(int i=1;i<=x-1;i++) {
if(!vis[i])
return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
for(int _=1;_<=t;_++) {
cin>>n;
vis.reset();ovis.reset(); // 初始化
for(int i=1;i<=n;i++) {
cin>>a[i];A=max(A,a[i]);ovis[a[i]]=true;
}
sort(&a[1],&a[n+1],less<int>());
int l=0,r=A;
while(l<r) {
for(int i=1;i<=A;i++)
vis[i]=ovis[i];
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}
// TLE https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785349

int l=0,r=n+1; // 如果n个数连续,那么就是n

for(int i=1;i<=n+1;i++)
vis[i]=ovis[i];

把上界换成n+1过了53.33% https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785676

但出现了WA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;
const int maxn=1e5+7,maxA=static_cast<int>(1e6)+7;
int n,t,a[maxA],A;
bitset<maxA> ovis,vis;
inline bool check(int x) {
for(int i=n;i>=1;i--) {
int ai=a[i];
if(ai<x)
break;
while(ai>>=1) {
if(!vis[ai] && ai<x) {vis[ai]=true;break;}
}
}
for(int i=1;i<=x-1;i++) {
if(!vis[i])
return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
for(int _=1;_<=t;_++) {
cin>>n;
vis.reset();ovis.reset(); // 初始化
for(int i=1;i<=n;i++) {
cin>>a[i];ovis[a[i]]=true;
}
sort(&a[1],&a[n+1],less<int>());
int l=0,r=n+1; // 如果n个数连续,那么就是n
while(l<r) {
for(int i=1;i<=n+1;i++)
vis[i]=ovis[i];
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}
// TLE https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785349

WA pass93.33% https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785979

应该是快了

增加了

1
2
3
4
for(int i=2;i<=n;i++) {
if(a[i]>=x) break;
if(a[i]==a[i-1]) vis[0]=true;break;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;
const int maxn=1e5+7,maxA=static_cast<int>(1e6)+7;
int n,t,a[maxA],A;
bitset<maxA> ovis,vis;
inline bool check(int x) {
for(int i=2;i<=n;i++) {
if(a[i]>=x) break;
if(a[i]==a[i-1]) vis[0]=true;break;
}
for(int i=n;i>=1;i--) {
int ai=a[i];
if(ai<x)
break;
while(true) {
ai>>=1;
if(!vis[ai] && ai<x) {vis[ai]=true;break;}
if(ai==0)
break;
}
}
for(int i=0;i<=x-1;i++) {
if(!vis[i])
return false;
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
for(int _=1;_<=t;_++) {
cin>>n;
vis.reset();ovis.reset(); // 初始化
for(int i=1;i<=n;i++) {
cin>>a[i];ovis[a[i]]=true;
}
sort(&a[1],&a[n+1],less<int>());
int l=0,r=n+1; // 如果n个数连续,那么就是n
while(l<r) {
for(int i=0;i<=n+1;i++)
vis[i]=ovis[i];
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}
// TLE https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785349
// 53.33% WA https://ac.nowcoder.com/acm/contest/view-submission?submissionId=71785676