T1
考虑没个点应该向左或者向右传多少,或者它自身接受左边传来了多少,右边传来了多少,因为一次只能传一个,所以传送的多少就是时间。
对所有的这些情况取 max。
/*
Date:
Source:
Knowledge:
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#define orz cout << "AK IOI" << "\n"
#define int long long
using namespace std;
const int maxn = 1e5 + 10;
int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
}
int Max(int a, int b){
return a > b ? a : b;
}
int Min(int a, int b){
return a < b ? a : b;
}
int n, ans, a[maxn], sum[maxn];
signed main()
{
//freopen("link.in", "r", stdin);
//freopen("link.out", "w", stdout);
n = read();
for(int i = 1; i <= n; i++) a[i] = read(), sum[i] = sum[i - 1] + a[i];
int tmp = sum[n] / n;
for(int i = 1; i <= n; i++)
{
int tmp1 = sum[i - 1] - (tmp * (i - 1)); //左边的
int tmp2 = sum[n] - sum[i] - tmp * (n - i); // 右边的
if(tmp1 < 0 && tmp2 < 0) ans = Max(ans, abs(tmp1 + tmp2));
else ans = Max(ans, Max(abs(tmp1), abs(tmp2)));
}
print(ans);
//fclose(stdin);
//fclose(stdout);
return 0;
}
T2
答案与城市的顺序无关,题目要求取走的数必须是所有已经取走的数的倍数或者约数。对数组进行排序,转化成取倍数的问题,用类似于埃氏筛的方法求解。
/*
Date:
Source:
Knowledge:
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#define orz cout << "AK IOI" << "\n"
using namespace std;
const int maxn = 1e6 + 10;
int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
}
int Max(int a, int b){
return a > b ? a : b;
}
int Min(int a, int b){
return a < b ? a : b;
}
int n, ans, a[maxn], f[maxn], cnt[maxn];
int main()
{
//freopen("pigeon.in", "r", stdin);
//freopen("pigeon.out", "w", stdout);
n = read();
for(int i = 1; i <= n; i++) a[i] = read(), f[a[i]]++, cnt[a[i]]++;
sort(a + 1, a + n + 1);
for(int i = 1; i <= maxn; i++)
{
if(f[i])
{
ans = Max(ans, f[i]);
for(int j = i + i; j <= maxn; j += i)
if(cnt[j]) f[j] = Max(f[j], f[i] + cnt[j]);
}
}
print(ans);
fclose(stdin);
fclose(stdout);
return 0;
}
T3
二分答案。
每次检验的时候会发现,一组卡牌中的一张选了会导致其他某组卡牌必须选另外一张,从而转化为 2-SAT 问题。
对于 所有卡牌战斗力的最大值减去最小值小于等于 100 的部分分,输出 \(0\)。
由于数据范围过大,无法直接 2-SAT 建图,注意到所有的边都是在一个区间里面的边,所以用线段树优化建图。
贴一下 std 吧。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int BUF_SIZE = 30;
char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + 1;
#define PTR_NEXT() \
{ \
buf_s ++; \
if (buf_s == buf_t) \
{ \
buf_s = buf; \
buf_t = buf + fread(buf, 1, BUF_SIZE, stdin); \
} \
}
#define readint(_n_) \
{ \
while (*buf_s != '-' && !isdigit(*buf_s)) \
PTR_NEXT(); \
bool register _nega_ = false; \
if (*buf_s == '-') \
{ \
_nega_ = true; \
PTR_NEXT(); \
} \
int register _x_ = 0; \
while (isdigit(*buf_s)) \
{ \
_x_ = _x_ * 10 + *buf_s - '0'; \
PTR_NEXT(); \
} \
if (_nega_) \
_x_ = -_x_; \
(_n_) = (_x_); \
}
#define readstr(_s_) \
{ \
while (!isupper(*buf_s)) \
PTR_NEXT(); \
char register *_ptr_ = (_s_); \
while (isupper(*buf_s) || *buf_s == '-') \
{ \
*(_ptr_ ++) = *buf_s; \
PTR_NEXT(); \
} \
(*_ptr_) = '\0'; \
}
#define readlonglong(_n_) \
{ \
while (*buf_s != '-' && !isdigit(*buf_s)) \
PTR_NEXT(); \
bool register _nega_ = false; \
if (*buf_s == '-') \
{ \
_nega_ = true; \
PTR_NEXT(); \
} \
long long register _x_ = 0; \
while (isdigit(*buf_s)) \
{ \
_x_ = _x_ * 10 + *buf_s - '0'; \
PTR_NEXT(); \
} \
if (_nega_) \
_x_ = -_x_; \
(_n_) = (_x_); \
}
#define wmt 1,(n<<1),1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=200010;
const int maxp=maxn+(maxn<<2);
const int maxm=maxn+maxp+maxn*40;
int n,size,cnt,en,t,dfn[maxp],low[maxp],s[maxp],belong[maxp],pos[maxn];
bool instack[maxp];
struct edge
{
int e;
edge *next;
}*v[maxp],ed[maxm];
void add_edge(int s,int e)
{
en++;
ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;
}
struct rec
{
int v,p;
rec(){}
rec(int a,int b)
{
v=a;p=b;
}
}z[maxn];
bool operator<(const rec &a,const rec &b)
{
return a.v<b.v;
}
void dfs(int p)
{
t++;
dfn[p]=low[p]=t;
instack[p]=true;
s[++size]=p;
for (edge *e=v[p];e;e=e->next)
if (!dfn[e->e])
{
dfs(e->e);
low[p]=min(low[p],low[e->e]);
}
else
{
if (instack[e->e]) low[p]=min(low[p],dfn[e->e]);
}
if (dfn[p]==low[p])
{
cnt++;
while (s[size]!=p)
{
belong[s[size]]=cnt;
instack[s[size]]=false;
size--;
}
belong[p]=cnt;
instack[p]=false;
size--;
}
}
void build(int l,int r,int rt)
{
if (l==r)
{
add_edge(rt+(n<<1),z[l].p<=n?z[l].p+n:z[l].p-n);
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
add_edge(rt+(n<<1),(rt<<1)+(n<<1));
add_edge(rt+(n<<1),(rt<<1|1)+(n<<1));
}
void insert(int l,int r,int rt,int nowl,int nowr,int p)
{
if (nowl<=l && r<=nowr)
{
add_edge(p,rt+(n<<1));
return;
}
int m=(l+r)>>1;
if (nowl<=m) insert(lson,nowl,nowr,p);
if (m<nowr) insert(rson,nowl,nowr,p);
}
bool check(int k)
{
en=0;cnt=0;
memset(v,0,sizeof(v));
memset(dfn,0,sizeof(dfn));
build(wmt);
int r=1,l=1;
for (int a=1;a<=(n<<1);a++)
{
int op,p=z[a].p;
if (p<=n) op=pos[p+n];
else op=pos[p-n];
while (r<=a && z[r].v <= z[a].v-k)
r++;
if (r<a && r>=1 && z[r].v > z[a].v-k)
{
if (op>=r && op<=a-1)
{
if (op>r) insert(wmt,r,op-1,z[a].p);
if (op<a-1) insert(wmt,op+1,a-1,z[a].p);
}
else insert(wmt,r,a-1,z[a].p);
}
while (l<=(n<<1) && z[l].v < z[a].v+k)
l++;
l--;
if (l>a && l<=(n<<1) && z[l].v < z[a].v+k)
{
if (op>=a+1 && op<=l)
{
if (op>a+1) insert(wmt,a+1,op-1,z[a].p);
if (op<l) insert(wmt,op+1,l,z[a].p);
}
else insert(wmt,a+1,l,z[a].p);
}
}
for (int a=1;a<=(n<<1);a++)
if (!dfn[a]) dfs(a);
for (int a=1;a<=n;a++)
if (belong[a]==belong[a+n]) return false;
return true;
}
int main()
{
readint(n);
int minv=0x3f3f3f3f,maxv=-0x3f3f3f3f;
int x=0;
for (int a=1;a<=n;a++)
{
int v1,v2;
readint(v1);
readint(v2);
z[++x]=rec(v1,a);
z[++x]=rec(v2,a+n);
minv=min(minv,min(v1,v2));
maxv=max(maxv,max(v1,v2));
}
if (maxv-minv+1 < n)
{
printf("0\n");
return 0;
}
sort(z+1,z+x+1);
for (int a=1;a<=(n<<1);a++)
pos[z[a].p]=a;
int l=0,r=1000000001;
while (l+1!=r)
{
int m=(l+r)>>1;
if (check(m)) l=m;
else r=m;
}
printf("%d\n",l);
return 0;
}