A
暴力覆盖。
#include<bits/stdc++.h>
using namespace std;
int n , m;
bool flag[200];
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
int main()
{
int n = read() , m = read();
for(int i = 1;i <= n;++i)
{
int l = read() , r = read();
for(int i = l;i <= r;++i) flag[i] = true;
}
int sum = 0;
for(int i = 1;i <= m;++i)
if(!flag[i]) sum++;
printf("%d\n",sum);
for(int i = 1;i <= m;++i)
if(!flag[i]) printf("%d ",i);
return 0;
}
B
不要求最小从左边开始一个个移
#include<bits/stdc++.h>
using namespace std;
int n;
char s[100] , t[100];
int sum[27];
int tmp[401000] , ans;
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
int main()
{
n = read();
scanf("%s%s",s+1,t+1);
for(int i = 1;i <= n;++i)
{
sum[s[i] - 'a']++;
sum[t[i] - 'a']--;
}
for(int i = 0;i <= 26;++i)
if(sum[i] != 0) {printf("-1");return 0;}
for(int i = 1;i <= n;++i)
{
if(s[i] == t[i]) continue;
char c = t[i];
int now = 0;
for(int j = i + 1;j <= n;++j)
if(s[j] == c) {now = j;break;}
for(int j = now - 1;j >= i;--j)
ans++ , swap(s[j] , s[j + 1]) , tmp[ans] = j;
}
printf("%d\n",ans);
for(int i = 1;i <= ans;++i)
printf("%d ",tmp[i]);
return 0;
}
C
先判个-1,然后对差值排个序
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n , k;
int a[101000] , b[101000] , c[101000];
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
int main()
{
n = read();k = read();
for(int i = 1;i <= n;++i)
a[i] = read() , b[i] = read() , c[i] = a[i] - b[i];
ll sum = 0 , need = 0;
for(int i = 1;i <= n;++i)
sum += b[i] , need += a[i];
if(sum > k) {printf("-1");return 0;}
sort(c + 1,c + n + 1);
need -= k;
int k = 0;
ll now = 0;
for(k = n + 1;k >= 1;--k)
{
now += c[k];
if(now >= need) break;
}
printf("%d\n",n - k + 1);
return 0;
}
D
这题的话有很多做法和想法
大多数想法都不太好操作
其实有个很简单的idea
先判完-1
先假定每次来回走
我们可以证明如果可以走肯定能走出一个来回走的序列
我们先假设每次都走
⌊sk⌋
⌊
s
k
⌋
把
rest
r
e
s
t
分配到前
rest
r
e
s
t
位,每位+1
来回跑就是了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n , s , k;
int a[2010000];
ll read()
{
ll sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
int main()
{
n = read();k = read();s = read();
if(k * (n-1) < s || k > s) {printf("NO");return 0;}
printf("YES\n");
if(s / k * k == s)
{
ll step = s / k;
ll now = 1;int flag= 1;
for(int i = 1;i <= k;++i)
{
now = now + step * flag;
flag = -flag;
cout<<now;printf(" ");
}
return 0;
}
ll step = s / k;
for(int i = 1;i <= k;++i)
a[i] = step;
ll rest = s - step * k;
for(int i = 1;i <= rest;++i)
a[i]++;
ll now = 1;int flag = 1;
for(int i = 1;i <= k;++i)
{
now = now + a[i] * flag;
flag = -flag;
cout<<now;printf(" ");
}
return 0;
}
E1
对于每个星星我们暴力判断能否以之为中心构成一个恒星并且算出能构成的最大恒星
暴力覆盖一下扫一遍就行
#include<bits/stdc++.h>
using namespace std;
#define ll long long
bool flag[200][200];
bool last[200][200];
char s[200];
int n , m , sum;
bool f[200][200];
struct anss{
int x , y , r;
}ans[10010];
ll read()
{
ll sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void solve(int x,int y)
{
int Max = min(n,m);
int now = 0;
for(int i = x + 1;i <= n;++i)
if(!flag[i][y]) break;
else now++;
Max = min(Max,now);now = 0;
for(int i = x - 1;i >= 1;--i)
if(!flag[i][y]) break;
else now++;
Max = min(Max,now);now = 0;
for(int i = y - 1;i >= 1;--i)
if(!flag[x][i]) break;
else now++;
Max = min(Max,now);now = 0;
for(int i = y + 1;i <= m;++i)
if(!flag[x][i]) break;
else now++;
Max = min(Max,now);now = 0;
if(Max == 0) return;
ans[++sum].x = x;ans[sum].y = y;ans[sum].r = Max;
last[x][y] = false;
for(int i = x + 1;i <= x + Max;++i) last[i][y] = false;
for(int i = x - 1;i >= x - Max;--i) last[i][y] = false;
for(int i = y + 1;i <= y + Max;++i) last[x][i] = false;
for(int i = y - 1;i >= y - Max;--i) last[x][i] = false;
// printf("#%d %d %d\n",x,y,Max);
return;
}
int main()
{
n = read();m = read();
for(int i = 1;i <= n;++i)
{
scanf("%s",s+1);
for(int j = 1;j <= m;++j)
if(s[j] != '.') flag[i][j] = last[i][j] = true;
}
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
if(flag[i][j]) solve(i,j);
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
if(last[i][j])
{printf("-1");return 0;}
printf("%d\n",sum);
for(int i = 1;i <= sum;++i)
printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].r);
return 0;
}
E2
考虑数据增大怎么办
我们算法的瓶颈在于判断以及算出最大的恒星
我们只要预处理出来每个点四个方向连续的星星个数
然后暴力覆盖就好了
什么?你觉得覆盖会TLE?
实际上复杂度可以证明出来是均摊的,不会TLE
By jaker_y, contest: Codeforces Round #501 (Div. 3), problem: (E2) Stars Drawing (Hard Edition), Accepted, #
#include<bits/stdc++.h>
using namespace std;
#define ll long long
bool flag[1010][1010];
bool last[1010][1010];
char s[1010];
int n , m , sum;
bool f[1010][1010];
int Left[1010][1010] , Right[1010][1010] , Up[1010][1010] , Down[1010][1010];
struct anss{
int x , y , r;
}ans[1001000];
ll read()
{
ll sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void solve(int x,int y)
{
int Max = min(n,m);
Max = min(Max,min(Left[x][y] , min(Right[x][y] , min(Up[x][y],Down[x][y]))));
if(Max == 0) return;
ans[++sum].x = x;ans[sum].y = y;ans[sum].r = Max;
last[x][y] = false;
for(int i = x + 1;i <= x + Max;++i) last[i][y] = false;
for(int i = x - 1;i >= x - Max;--i) last[i][y] = false;
for(int i = y + 1;i <= y + Max;++i) last[x][i] = false;
for(int i = y - 1;i >= y - Max;--i) last[x][i] = false;
return;
}
void pre()
{
int now;
for(int i = 1;i <= n;++i)
{
now = 0;
for(int j = 1;j <= m;++j)
{
Left[i][j] = now;
if(flag[i][j]) now++;
else now = 0;
}
}
for(int i = 1;i <= n;++i)
{
now = 0;
for(int j = m;j >= 1;--j)
{
Right[i][j] = now;
if(flag[i][j]) now++;
else now = 0;
}
}
for(int j = 1;j <= m;++j)
{
now = 0;
for(int i = 1;i <= n;++i)
{
Up[i][j] = now;
if(flag[i][j]) now++;
else now = 0;
}
}
for(int j = 1;j <= m;++j)
{
now = 0;
for(int i = n;i >= 1;--i)
{
Down[i][j] = now;
if(flag[i][j]) now++;
else now = 0;
}
}
return;
}
int main()
{
n = read();m = read();
for(int i = 1;i <= n;++i)
{
scanf("%s",s+1);
for(int j = 1;j <= m;++j)
if(s[j] != '.') flag[i][j] = last[i][j] = true;
}
pre();
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
if(flag[i][j]) solve(i,j);
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
if(last[i][j])
{printf("-1");return 0;}
printf("%d\n",sum);
for(int i = 1;i <= sum;++i)
printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].r);
return 0;
}