2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest
C Evolution Game
题目链接
题意:有n个不同版本的野兽,定义属性:第 i 个野兽有 i 个眼睛和 h[i] 个角,你可以任意从中选择一个野兽进行进化,每次进化角数量必须增加,而且进化后假设有a 个眼睛 b个角,假设h[i]=b,那么abs(a-i)<=w,否则不能进化,求最多的进化次数。
思路:进化前向进化后建立单项边,跑标记的BFS
By sharp_cone, contest: 2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest, problem: (C) Evolution Game, Accepted, #
#include <bits/stdc++.h>
#define maxn 5005
#define inf 0x3f3f3f3f
using namespace std;
int n,w;
int h[maxn];
int indeg[maxn];
int vis[maxn];
vector <int>G[maxn];
void input(){
scanf("%d%d",&n,&w);
for(int i=1;i<=n;i++){
// h[i]=i;
scanf("%d",&h[i]);
vis[i]=-1;
}
for(int i=1;i<=n;i++){
int temp=inf;
for(int j=1;j<=w;j++){
if(i+j>n)break;
if(h[i]<h[i+j]&&h[i+j]<=temp){
temp=h[i+j];
G[i].push_back(i+j);
indeg[i+j]++;
}
}
temp=inf;
for(int j=1;j<=w;j++){
if(i-j<1)break;
if(h[i]<h[i-j]&&h[i-j]<=temp){
temp=h[i-j];
G[i].push_back(i-j);
indeg[i-j]++;
}
}
}
// cout<<"!!!"<<endl;
}
struct node{
int index,step;
};
void solve(){
queue <node>q;
for(int i=1;i<=n;i++)
if(!indeg[i]){
q.push((node){i,0});
vis[i]=0;
}
int ans=0;
while(!q.empty()){
node f=q.front();
// cout<<f.index<<' '<<f.step<<endl;
ans=max(ans,f.step);
q.pop();
for(int i=0;i<G[f.index].size();i++){
int v=G[f.index][i];
if(vis[v]!=-1&&vis[v]==f.step+1)
continue;
vis[v]=f.step+1;
q.push((node){v,f.step+1});
}
}
printf("%d\n",ans);
}
int main(){
input();
solve();
}
D Bus Stop
题目链接
题意:有n个房子的坐标,你要建立公交车站,使得每个房子离最近的车站不过10公里,求最少的车站。
思路:贪心,在房子后10米建公交车站
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 5;
int a[maxn];
int main() {
int m;
scanf("%d", &m);
while (m--) {
int n;
scanf("%d", &n);
if(n==0){
printf("0\n");
continue;
}
for (int i = 1; i <= n; i++)scanf("%d", &a[i]);
int cur = a[1] + 10;
int cnt = 1;
for (int i = 2; i <= n; i++) {
if (a[i] <= cur + 10)continue;
cnt++;
cur = a[i] + 10;
}
cout << cnt << endl;
}
}
/*
2
5
1 2 3 200 210
4
10 30 80 200
*/ E How Many Groups
G Communication
题目链接
题意:给一些有向边,如果两个点可以互达,那么这两个点属于同一组,求你给有向图分组。
思路:求强连通,搜索
#include <bits/stdc++.h>
#define maxn 505
using namespace std;
const int inf = 0x3f3f3f3f;
int a[maxn];
int g[maxn][maxn];
vector<int>v[maxn];
int vis[maxn];
void dfs(int x, int fa) {
for (int y : v[x]) {
if (!vis[y] && y != fa) {
vis[y] = 1;
dfs(y, x);
}
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
int m;
scanf("%d", &m);
memset(g, 0, sizeof g);
for (int i = 1; i <= m; i++) {
int x, y;
scanf("%d%d", &x, &y);
x++; y++;
g[x][y] = 1;
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
g[i][j] |= g[i][k] & g[k][j];
}
}
}
for (int i = 1; i <= n; i++) {
v[i].clear();
vis[i] = 0;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (g[i][j] && g[j][i]) {
v[i].push_back(j);
v[j].push_back(i);
//cout << "i : j " << i << " " << j << endl;
}
}
}
int cnt = 0;
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
//cout << "** " << i << endl;
vis[i] = 1;
cnt++;
dfs(i, -1);
}
}
printf("%d\n", cnt);
}
}
/*
3
6
2 0 5 5 0
5
7 0 1 0 2 1 0 1 3 2 4 3 1 4 2
3
4 0 1 0 2 1 0 1 2
*/ H As Rich as Crassus
题目链接
题意:给定三个余数和答案,求满足条件的被余数的开方
思路:扩展中国剩余定理,得到数,开3次方求能否存在,不能则+LCM。存在精度问题,则if aaa<res then a=a+1。可解决。
#include <bits/stdc++.h>
#define maxn 5
#define EPS 1e-10
typedef long long ll;
using namespace std;
ll bi[maxn], ai[maxn];
ll gcd(ll a, ll b) {
while (b ^= a ^=b^= a %= b);
return a;
}
ll lcm(ll a, ll b) {
return a * b / gcd(a, b);
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
ll gcd = exgcd(b, a%b, x, y);
ll tp = x;
x = y;
y = tp - a / b * y;
return gcd;
}
ll qmul(ll a, ll b, ll m) {
ll ans = 0;
ll k = a;
ll f = 1;
if (k<0) {
f = -1;
k *= -1;
}
if (b<0) {
f *= -1;
b *= -1;
}
while (b) {
if (b & 1)
ans = (ans + k) % m;
k = (k + k) % m;
b >>= 1;
}
return ans * f;
}
ll excrt() {
ll x, y, k;
ll M = bi[1], ans = ai[1];
for (int i = 2; i <= 3; i++) {
ll a = M, b = bi[i], c = (ai[i] - ans % b + b) % b;
ll gcd = exgcd(a, b, x, y);
ll bg = b / gcd;
if (c%gcd != 0)
return -1;
x = qmul(x, c / gcd, bg);
ans += x * M;
M *= bg;
ans = (ans%M + M) % M;
}
return (ans%M + M) % M;
}
void input() {
for (int i = 1; i <= 3; i++)
scanf("%lld", &bi[i]);
for (int i = 1; i <= 3; i++)
scanf("%lld", &ai[i]);
}
long double temp;
bool check(ll res){
temp=pow(res,1.0/3);
// cout<<temp<<endl;
return temp*temp*temp-1.0*res<EPS;
}
void solve() {
ll res = excrt();
ll LCM = lcm(lcm(bi[1], bi[2]), bi[3]);
while (!check(res)) {
res += LCM;
}
if(temp*temp*temp<res)
printf("%lld\n",(ll)temp+1);
else
printf("%lld\n",(ll)temp);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
input();
solve();
}
}
/*
2
6 11 19
5 4 11
25 36 7
16 0 6
*/ J Floating-Point Hazard
题目链接
题意:解给定的式子
思路:积分,待补
K The Stream of Corning 2
题目链接
题意:两种操作 1:l val r 表示在[l,r]时间内有val值,2:l k 求时间为l时,存在第k大值。
思路:优先队列维护右区间,主席树维护区间第k大
#include <bits/stdc++.h>
#define maxn 100005
#define maxN 1000005
using namespace std;
int n;
int opt,l,val,r;
struct node{
int l,r;
int cnt;
node(){
l=r=cnt=0;
}
}T[maxN*22];
int rt[maxn*2];
int tot=0;
void update(int &x,int y,int l,int r,int pos,int val){
T[++tot]=T[y];
T[tot].cnt+=val;
x=tot;
if(l==r)
return;
int mid=(l+r)>>1;
if(pos<=mid)
update(T[x].l,T[y].l,l,mid,pos,val);
else
update(T[x].r,T[y].r,mid+1,r,pos,val);
}
int query(int x,int y,int l,int r,int k){
if(l==r)
return l;
int mid=(l+r)>>1;
int sum=T[T[y].l].cnt-T[T[x].l].cnt;
if(k<=sum)
return query(T[x].l,T[y].l,l,mid,k);
else
return query(T[x].r,T[y].r,mid+1,r,k-sum);
}
void input(){
tot=0;
scanf("%d",&n);
priority_queue<pair<int,int> >q;
int now=1;
for(int i=1;i<=n;i++){
scanf("%d",&opt);
if(opt==1){
scanf("%d%d%d",&l,&val,&r);
update(rt[now],rt[now-1],1,maxN,val,1);
now++;
q.push(make_pair(-r,val));
}else{
scanf("%d%d",&l,&val);
while(!q.empty()&&-q.top().first<l){
update(rt[now],rt[now-1],1,maxN,q.top().second,-1);
now++;
q.pop();
}
int ans=query(rt[0],rt[now-1],1,maxN,val);
if(ans>1000000)
printf("-1\n");
else
printf("%d\n",ans);
}
}
}
int main(){
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
printf("Case %d:\n",cas );
input();
}
}
/*
1
10
1 1 10 7
1 2 9 4
2 4 1
1 5 2 6
2 6 2
2 7 2
1 8 2 20
1 9 1 15
1 10 3 13
2 11 3
*/ L Largest Allowed Area
题目链接
题意:求01矩阵中只有一个1的最大子矩阵
思路:nnlogn。二分+枚举+快读,卡过。正解是用单调队列。
#include <bits/stdc++.h>
#define maxn 1005
using namespace std;
int n,m;
int g[maxn][maxn];
int sum[maxn][maxn];
bool check(int x){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i+x-1>n||j+x-1>m)
break;
if(sum[i+x-1][j+x-1]+sum[i-1][j-1]-sum[i-1][j+x-1]-sum[i+x-1][j-1]==1){
// cout<<i<<" "<<j<<" "<<x<<endl;
return 1;
}
}
}
return 0;
}
int scan(){
int res=0,flag=0;
char ch;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+(ch-'0');
return flag?-res:res;
}
void input(){
n=scan();m=scan();
int r=min(n,m);
r++;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
g[i][j]=scan();
sum[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+g[i][j];
}
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=m;j++){
// printf("%d ",sum[i][j]);
// }
// printf("\n");
// }
int l=0;
int ans;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)){
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
printf("%d\n",ans);
}
int main(){
int t;
t=scan();
while(t--){
input();
// solve();
}
}
/*
4 4
0 0 0 0
0 1 0 1
0 0 0 0
0 1 0 1
10 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
20 10
1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0
*/
京公网安备 11010502036488号