B.蔬菜
非正解二维莫队碾过
vegetable
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define int long long
using namespace std;
inline int read(){
int x = 0, w = 1;
char ch = getchar();
for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x * w;
}
inline void write(register int x){
if(x < 0) x = ~x + 1, putchar('-');
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int s1, s2;
const int ss = 205;
struct node{
int lx, ly, rx, ry, id;
inline bool operator < (const node &a) const {
register int lx1 = (lx - 1) / s1 + 1, lx2 = (a.lx - 1) / s1 + 1;
register int rx1 = (rx - 1) / s1 + 1, rx2 = (a.rx - 1) / s1 + 1;
register int ly1 = (ly - 1) / s2 + 1, ly2 = (a.ly - 1) / s2 + 1;
return lx1 == lx2 ? rx1 == rx2 ? ly1 == ly2 ? (ly1 & 1) ? ry < a.ry : ry > a.ry : (rx1 & 1) ? ly1 < ly2 : ly1 > ly2 : (lx1 & 1) ? rx1 < rx2 : rx1 > rx2 : lx1 < lx2;
}
}q[1000005];
int a[ss][ss], b[40005], cnt, s[40005], sum, ans[1000005];
inline int binary_search(register int x){
register int l = 1, r = cnt;
while(l < r){
register int mid = l + r >> 1;
if(b[mid] >= x) r = mid;
else l = mid + 1;
}
return l;
}
inline void add1(register int u, register int l, register int r){
for(register int i = l; i <= r; i++){
sum += (s[a[u][i]] * 2 + 1);
s[a[u][i]]++;
}
}
inline void add2(register int u, register int l, register int r){
for(register int i = l; i <= r; i++){
sum += (s[a[i][u]] * 2 + 1);
s[a[i][u]]++;
}
}
inline void del1(register int u, register int l, register int r){
for(register int i = l; i <= r; i++){
sum += (1 - s[a[u][i]] * 2);
s[a[u][i]]--;
}
}
inline void del2(register int u, register int l, register int r){
for(register int i = l; i <= r; i++){
sum += (1 - s[a[i][u]] * 2);
s[a[i][u]]--;
}
}
signed main(){
freopen("vegetable.in", "r", stdin);
freopen("vegetable.out", "w", stdout);
register int r = read(), c = read(), Q = read();
s1 = sqrt(r), s2 = sqrt(c);
for(register int i = 1; i <= r; i++)
for(register int j = 1; j <= c; j++)
a[i][j] = read(), b[++cnt] = a[i][j];
sort(b + 1, b + 1 + cnt);
cnt = unique(b + 1, b + 1 + cnt) - b - 1;
for(register int i = 1; i <= r; i++)
for(register int j = 1; j <= c; j++)
a[i][j] = binary_search(a[i][j]);
/*
for(register int i = 1; i <= r; i++, puts(""))
for(register int j = 1; j <= c; j++)
cout << a[i][j] << " ";
*/
for(register int i = 1; i <= Q; i++)
q[i] = (node){read(), read(), read(), read(), i};
sort(q + 1, q + 1 + Q);
register int lx = 1, ly = 1, rx = 1, ry = 1;
s[a[1][1]] = 1, sum = 1;
for(register int i = 1; i <= Q; i++){
while(lx > q[i].lx) add1(--lx, ly, ry);
while(rx < q[i].rx) add1(++rx, ly, ry);
while(ry < q[i].ry) add2(++ry, lx, rx);
while(ly > q[i].ly) add2(--ly, lx, rx);
while(lx < q[i].lx) del1(lx++, ly, ry);
while(rx > q[i].rx) del1(rx--, ly, ry);
while(ry > q[i].ry) del2(ry--, lx, rx);
while(ly < q[i].ly) del2(ly++, lx, rx);
ans[q[i].id] = sum;
}
for(register int i = 1; i <= Q; i++)
cout << ans[i] << '
';
return 0;
}
C.联盟
真的写吐了
改了四节课
昨天下午出了第一个部分分的时候激动的差点哭了出来
草
然后今天上午才把(60pts)完完整整码完
满分做法是(o(n))处理树及子树的直径
然而感觉实现有点困难
啊不
是的确困难
写不出来惹
回头再说
Leaque
/* cinput
4
1 2
2 3
3 4
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define min(a, b) (a) < (b) ? (a) : (b)
using namespace std;
inline int read(){
int x = 0, w = 1;
char ch = getchar();
for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x * w;
}
inline void write(register int x){
if(x < 0) x = ~x + 1, putchar('-');
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const int ss = 300010;
struct node{
int from, to, nxt;
}edge[ss << 1];
int head[ss], tot = 1;
inline void add(register int u, register int v){
edge[++tot].to = v;
edge[tot].from = u;
edge[tot].nxt = head[u];
head[u] = tot;
}
bool vis[ss << 1];
int dis[ss], fa[ss], from, to, id, maxx, dep[ss];
inline void dfs(register int u, register int f){
if(dis[u] > maxx) to = u, maxx = dis[u];
dep[u] = dep[f] + 1;
for(register int i = head[u]; i; i = edge[i].nxt){
register int v = edge[i].to;
if(v == f || vis[i]) continue;
dis[v] = dis[u] + 1;
fa[v] = u;
dfs(v, u);
}
}
inline void diameter(register int u){}
inline int jump(register int u, register int d){
while(d--) u = fa[u];
return u;
}
inline int getlen(register int id){
register int u = edge[id].from;
register int v = edge[id].to;
vis[id] = vis[id ^ 1] = 1;
memset(dis, 0, sizeof dis); to = 0;
maxx = -1, dfs(u, u);
memset(dis, 0, sizeof dis);
maxx = -1, dfs(to, to);
register int len1 = dis[to];
memset(dis, 0, sizeof dis); to = 0;
maxx = -1, dfs(v, v);
memset(dis, 0, sizeof dis);
maxx = -1, dfs(to, to);
register int len2 = dis[to];
register int len = max(len1, len2);
len = max(len, (len1 + 1) / 2 + (len2 + 1) / 2 + 1);
vis[id] = vis[id ^ 1] = 0;
return len;
}
int a[ss], cnt;
signed main(){
freopen("league.in", "r", stdin);
freopen("league.out", "w", stdout);
register int n = read();
memset(head, 0, sizeof head);
for(register int i = 1; i <= n - 1; i++){
register int u = read(), v = read();
add(u, v);
add(v, u);
}
register int ans = 0x7fffffff;
for(register int i = 2; i <= tot; i += 2){
register int len = getlen(i);
if(len < ans) ans = len, a[cnt = 1] = i / 2;
else if(len == ans) a[++cnt] = i / 2;
}
write(ans), puts("");
write(cnt), printf(" ");
for(register int i = 1; i <= cnt; i++)
write(a[i]), printf(" ");
puts("");
register int id = 2 * a[1];
register int u = edge[id].from;
register int v = edge[id].to;
write(u), printf(" "), write(v), printf(" ");
vis[id] = vis[id ^ 1] = 1;
memset(dis, 0, sizeof dis); to = 0;
maxx = -1; dfs(u, u);
from = to;
memset(dis, 0, sizeof dis);
maxx = -1, dfs(to, to);
register int getdis = dis[to];
register int depp = -1;
register int skip = 0;
if(depp < dep[from]) depp = dep[from], skip = from;
if(depp < dep[to]) depp = dep[to], skip = to;
write(jump(skip, getdis + 1 >> 1)), printf(" ");
memset(dis, 0, sizeof dis); to = 0;
maxx = -1, dfs(v, v);
from = to;
memset(dis, 0, sizeof dis);
maxx = -1, dfs(to, to);
getdis = dis[to];
depp = -1;
if(depp < dep[from]) depp = dep[from], skip = from;
if(depp < dep[to]) depp = dep[to], skip = to;
write(jump(skip, getdis + 1 >> 1)), printf(" ");
return 0;
}
D.水滴
最简单的一道了吧。。。
然而考场只有可怜巴巴的(40pts)暴力分
尺取法
每次询问当中(O(n))扫一遍
对左右端点进行扩展
Drop
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define min(a, b) (a) < (b) ? (a) : (b)
using namespace std;
inline int read(){
int x = 0, w = 1;
char ch = getchar();
for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return x * w;
}
inline void write(register int x){
if(x < 0) x = ~x + 1, putchar('-');
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const int ss = 200005;
int d[ss], cnt[ss], kill[ss];
signed main(){
freopen("drop.in", "r", stdin);
freopen("drop.out", "w", stdout);
register int T = read();
while(T--){
register int ans = 0x7fffffff;
memset(cnt, 0, sizeof cnt);
memset(kill, 0, sizeof kill);
register int n = read(), m = read(), q = read();
for(register int i = 1; i <= n; i++) d[i] = read();
for(register int i = 1; i <= q; i++){
register int pos = read();
kill[pos] = read();
}
register int l = 1, r = 1, tmp = 0;
while(l <= r && r <= n){
if(++cnt[d[r]] == kill[d[r]]) tmp++;
while(cnt[d[l]] > kill[d[l]]) cnt[d[l]]--, l++;
if(tmp == q) ans = min(ans, r - l + 1);
r++;
}
if(ans == 0x7fffffff) puts("DESTROY ALL");
else write(ans), puts("");
}
return 0;
}