8.10 Round 1
要提高代码能力
T1:https://www.luogu.org/problem/T93255
送分背包
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define O(x) cout << #x << " " << x << endl; #define B cout << "breakpoint" << endl; #define clr(a) memset(a,0,sizeof(a)); inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } typedef long long ll; const int N = 55; const int mod = 1e9 + 7; ll f[N][N][2050]; int main() { freopen("number.in","r",stdin); freopen("number.out","w",stdout); int n = read(),K = read(),s = read(); f[0][0][0] = 1ll; for(int i = 1;i <= n;i++) for(int j = 0;j <= K;j++) for(int k = 0;k <= s;k++) { (f[i][j][k] += f[i - 1][j][k]) %= mod; if(k >= i && j >= 1) (f[i][j][k] += f[i - 1][j - 1][k - i]) %= mod; } printf("%lld",f[n][K][s]); }
T2:https://www.luogu.org/problem/T93256
一个圆恰好被若干圆分割时,对答案贡献2
其余贡献1
将圆按半径排序,线段树维护哪些点被覆盖过
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define O(x) cout << #x << " " << x << endl; #define B cout << "breakpoint" << endl; #define clr(a) memset(a,0,sizeof(a)); inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } typedef long long ll; const int maxn = 6e5 + 5; struct node1 { int l,r,ctr,d; bool operator < (const node1& b) const { return d < b.d; } }a[maxn]; int b[maxn]; int tot; bool vis[maxn]; struct seg_tr { int sum[maxn << 2],lazy[maxn << 2]; #define ls i << 1 #define rs i << 1 | 1 inline void up(int i) { sum[i] = sum[ls] + sum[rs]; } inline void down(int i,int l,int r) { int mid = l + r >> 1; if(lazy[i]) lazy[ls] = lazy[rs] = 1,sum[ls] = mid - l + 1,sum[rs] = r - mid,lazy[i] = 0; } void change(int i,int l,int r,int ql,int qr) { if(l == ql && r == qr) { sum[i] = r - l + 1; lazy[i] = 1; return; } down(i,l,r); int mid = l + r >> 1; if(qr <= mid) change(ls,l,mid,ql,qr); else if(ql > mid) change(rs,mid + 1,r,ql,qr); else change(ls,l,mid,ql,mid),change(rs,mid + 1,r,mid + 1,qr); up(i); } int query(int i,int l,int r,int ql,int qr) { if(l == ql && r == qr) return sum[i]; down(i,l,r); int mid = l + r >> 1; if(qr <= mid) return query(ls,l,mid,ql,qr); else if(ql > mid) return query(rs,mid + 1,r,ql,qr); else return query(ls,l,mid,ql,mid) + query(rs,mid + 1,r,mid + 1,qr); } }T; int main() { freopen("circle.in","r",stdin); freopen("circle.out","w",stdout); int n = read(); for(int i = 1;i <= n;i++) { a[i].ctr = read(); int x = read(); a[i].l = a[i].ctr - x; a[i].r = a[i].ctr + x; b[++tot] = a[i].l; b[++tot] = a[i].r; a[i].d = x; } sort(b + 1,b + 1 + tot); int l = unique(b + 1,b + 1 + tot) - b - 1; tot = l; for(int i = 1;i <= n;i++) { a[i].l = lower_bound(b + 1,b + 1 + tot,a[i].l) - b; a[i].r = lower_bound(b + 1,b + 1 + tot,a[i].r) - b; } sort(a + 1,a + 1 + n); int ans = 1; for(int i = 1;i <= n;i++) { if(T.query(1,1,n,a[i].l,a[i].r - 1) == a[i].r - a[i].l) ans += 2; else ans += 1; T.change(1,1,n,a[i].l,a[i].r - 1); } printf("%d",ans); } /* 4 7 5 -9 11 11 9 0 20 */
T3:https://www.luogu.org/problem/T93257
考场想的正解,没写出来
要提高代码能力
先缩点,枚举哪一条边反向,可以看出,需要维护1->i的最长路径,i->1的最长路径
所以spfa跑最长路;考场上我想拆点,代码会复杂;其实对于点的最短路也可以一样跑,不需要拆开
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define O(x) cout << #x << " " << x << endl; #define B cout << "breakpoint" << endl; #define clr(a) memset(a,0,sizeof(a)); #define pii pair<int,int> #define mp make_pair #define fi first #define se second inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } typedef long long ll; const int maxn = 2e5 + 5; struct node { int u,v; }a[maxn]; struct edge { int to,next; }e[maxn],rev[maxn]; int head[maxn],cnt; void adde2(int u,int v) { rev[++cnt].next = head[u],head[u] = cnt,rev[cnt].to = v; } int fir[maxn],alloc; void adde1(int u,int v) { e[++alloc].next = fir[u],fir[u] = alloc,e[alloc].to = v; } int dfn[maxn],idx,col[maxn],b[maxn],tot,low[maxn],st[maxn],top,n,m; bool instack[maxn]; void tarjan(int u) { low[u] = dfn[u] = ++idx; instack[u] = 1; st[++top] = u; for(int i = fir[u];i;i = e[i].next) { int v = e[i].to; if(!dfn[v]) { tarjan(v); low[u] = min(low[u],low[v]); } else if(instack[v]) low[u] = min(low[u],dfn[v]); } if(low[u] == dfn[u]) { tot++; while(st[top] != u) { int k = st[top]; col[k] = tot; instack[k] = 0; b[tot]++; top--; } col[u] = tot; instack[u] = 0,b[tot]++; top--; } } int d1[maxn],s; bool vis[maxn]; void spfa1() { clr(vis); queue<int> q; q.push(s); d1[s] = b[s]; while(q.size()) { int u = q.front(); q.pop(); //O(u); //printf("%d %d\n",d1[u],u); vis[u] = 0; for(int i = fir[u];i;i = e[i].next) { int v = e[i].to; if(d1[v] < d1[u] + b[v]) { d1[v] = d1[u] + b[v]; if(!vis[v]) vis[v] = 1,q.push(v); } } } }//d1:1->其他,d2:其他->1 int d2[maxn]; void spfa2() { clr(vis); queue<int> q; q.push(s); d2[s] = b[s]; while(q.size()) { int u = q.front(); q.pop(); //printf("%d %d\n",d2[u],u); vis[u] = 0; for(int i = head[u];i;i = rev[i].next) { int v = rev[i].to; if(d2[v] < d2[u] + b[v]) { d2[v] = d2[u] + b[v]; if(!vis[v]) vis[v] = 1,q.push(v); } } } } int main() { freopen("wander.in","r",stdin); freopen("wander.out","w",stdout); n = read(),m = read(); for(int i = 1;i <= m;i++) { int u = read(),v = read(); a[i].u = u,a[i].v = v; adde1(u,v); } for(int i = 1;i <= n;i++) if(!dfn[i]) tarjan(i); clr(fir); alloc = 0; clr(head); cnt = 0; //for(int i = 1;i <= n;i++) printf("%d ",col[i]); //printf("\n"); for(int i = 1;i <= m;i++) { int u = col[a[i].u],v = col[a[i].v]; if(u == v) continue; //printf("%d %d\n",u,v); adde1(u,v); adde2(v,u); } s = col[1]; //O(s); spfa1(); spfa2(); int ans = b[s]; for(int i = 1;i <= m;i++) { int u = col[a[i].u],v = col[a[i].v]; if(u == v) continue; //printf("%d %d\n",u,v); if(!d1[v] || !d2[u]) continue; ans = max(ans,d1[v] + d2[u] - b[s]); } printf("%d",ans); } /* 7 10 1 2 3 1 2 5 2 4 3 7 3 5 3 6 6 5 7 2 4 7 */