【2021夏纪中游记】2021.8.16模拟赛
比赛概括:
\(\mathrm{sum}=25+0+0+0\)
换组别了爆零我真开心。
T1 [USACO21FEB] No Time to Dry P:
题目大意:
思路:
莫队,并用线段树求出一个点左右与其相同的点的位置。
代码:
const int N = 2e5 + 10;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
int n, q, S;
struct Question
{
int l, r, x, id;
bool operator < (const Question &a) const
{
return x < a.x || (x == a.x && r < a.r);
}
}b[N];
int a[N], Ans[N], lst[N];
int v[N], L[N], R[N];
struct SegmentTree
{
struct Tree
{
int l, r, val, lzy;
}t[N << 2];
void Build(int p, int l, int r)
{
t[p].l = l, t[p].r = r, t[p].lzy = -1;
if (l == r) {t[p].val = a[l]; return;}
int mid = l + r >> 1;
Build (p << 1, l, mid);
Build (p << 1 | 1, mid + 1, r);
t[p].val = min(t[p << 1].val, t[p << 1 | 1].val);
}
int Query(int p, int l, int r)
{
if (t[p].r < l || r < t[p].l) return 1e9;
if (l <= t[p].l && t[p].r <= r) return t[p].val;
int ans = 0;
ans = min(Query(p << 1, l, r), Query(p << 1 | 1, l, r));
return ans;
}
}t;
int main()
{
n = Read(), q = Read();
S = 450;
for (int i = 1; i <= n; i++)
a[i] = Read();
for (int i = 1; i <= q; i++)
b[i].l = Read(), b[i].r = Read(), b[i].x = b[i].l / S + 1, b[i].id = i;
sort (b + 1, b + 1 + q);
t.Build(1, 1, n);
for (int i = 1; i <= n; lst[a[i]] = i, i++)
if (lst[a[i]]) L[i] = t.Query(1, lst[a[i]], i) < a[i]? -1: lst[a[i]];
else L[i] = -1;
memset (lst, 0, sizeof lst);
for (int i = n; i; lst[a[i]] = i, i--)
if (lst[a[i]]) R[i] = t.Query(1, i, lst[a[i]]) < a[i]? n + 5: lst[a[i]];
else R[i] = n + 5;
for (int i = 1, tl = 1, tr = 0, ans = 0; i <= q; i++)
{
int l = b[i].l, r = b[i].r;
while (tl > l) tl--, ans += R[tl] > tr;
while (tl < l) ans -= R[tl] > tr, tl++;
while (tr < r) tr++, ans += L[tr] < tl;
while (tr > r) ans -= L[tr] < tl, tr--;
Ans[b[i].id] = ans;
}
// for (int i = 1; i <= n; i++)
// printf ("%d %d\n", L[i], R[i]);
for (int i = 1; i <= q; i++)
printf ("%d\n", Ans[i]);
return 0;
}
T2 [USACO21FEB] Minimizing Edges P:
题目大意:
思路:
不会。
T3 [USACO21FEB] Counting Graphs P:
题目大意:
思路:
不会。
T4 Count the Cows G:
题目大意:
思路:
可以发现,图形其实是 “x” 型的分型图,那么分类讨论倍增即可。
calc(v,n)
表示函数 \(y=-x+v\) 图像经过的一的个数。
query(x,y,n)
表示 \((0,0)\) 到 \((x,y)\) 的一的个数。
代码:
const int N = 50;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
unsigned ll x, y, d;
unsigned ll pw[N];
int a[3][3] = {{1, 0, 1}, {0, 2, 0}, {1, 0, 3}};
ll calc (ll v, ll n)
{
if (n == 1) return 1;
if (n == 3)
{
if(v == 0) return 3;
if(v == 1) return 0;
return 1;
}
ll m = n / 3;
if (v < m) return 3ll * calc(v, m);
if (v == m) return 0;
if (v < 2ll * m) return calc(2ll * m - v, m);
return calc (v - 2ll * m, m);
}
ll query(ll x, ll y, ll n)
{
if (n == 3) return a[x][y];
if (x > y) x ^= y ^= x ^= y;
ll v = y - x, m = n / 3ll;
ll tmp = calc(v, m);
if (v < m)
{
if (y < m) return query(x, y, m);
if (x < m) return tmp;
if (y < 2ll * m) return tmp + query(x - m, y - m, m);
if (x < 2ll * m) return 2ll * tmp;
return 2ll * tmp + query(x - 2ll * m, y - 2ll * m, m);
}
if (v == m) return 0;
if (v < 2ll * m)
{
if (y < 2ll * m) return 0;
if (x >= m) return calc(2ll * m - v, m);
return query(x, y - 2ll * m, m);
}
return query(x, y - 2ll * m, m);
}
ll Query(ll x, ll y)
{
if (x < 0 || y < 0) return 0;
if (x > y) x ^= y ^= x ^= y;
ll v = y - x;
int k = upper_bound(pw, pw + 41, y) - pw;
return query(x, y, pw[k]);
}
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
pw[0] = 1;
for (int i = 1; i <= 40; i++) pw[i] = pw[i - 1] * 3;
for (int t = Read(); t--; )
{
d = Read(), x = Read(), y = Read();
printf ("%lld\n", Query(x + d, y + d) - Query(x - 1, y - 1));
}
return 0;
}