20230527 板子 板子和板子
P1038 [NOIP2003 提高组] 神经网络
发现对于 i 我们必须知道 i 之前所有 j 的值 想到拓扑
然后发现根据题意 必然是一个 DAG 图 直接做就行
code:
#include<bits/stdc++.h>
using namespace std ;
const int N = 1e5 + 0721 ;
int head[N] , nxt[N] , to[N] , w[N] , cnt ;
int c[N] , v[N] ;
bool sr[N] ;
int rd[N] , cd[N] , topo[N] , top ;
int n , p ;
struct node{
int id , c ;
}a[N];
bool cmp( node x , node y ){
return x.id < y.id ;
}
void cmb( int x , int y , int z ){
to[++cnt] = y ;
w[cnt] = z ;
nxt[cnt] = head[x] ;
head[x] = cnt ;
rd[y]++ , cd[x]++ ;
}
int main () {
scanf("%d%d" ,&n ,&p ) ;
for( int i = 1 ; i <= n ; ++i )
scanf("%d%d" ,&c[i] ,&v[i] ) ;
for( int i = 1 ; i <= p ; ++i ){
int x , y , z ;
scanf("%d%d%d" ,&x ,&y ,&z ) ;
cmb( x , y , z ) ;
}
for( int i = 1 ; i <= n ; ++i ){
if( rd[i] == 0 )
topo[++top] = i , sr[i] = 1 ;
}
for( int i = 1 ; i <= top ; ++i ){
int x = topo[i] ;
for( int j = head[x] ; j ; j = nxt[j] ){
int y = to[j] ;
rd[y]-- ;
if( rd[y] == 0 )
topo[++top] = y ;
}
}
for( int i = 1 ; i <= top ; ++i ){
int x = topo[i] ;
if( !sr[x] )
c[x] -= v[x] ;
for( int j = head[x] ; j ; j = nxt[j] ){
int y = to[j] ;
if( c[x] > 0 ){
c[y] += c[x] * w[j] ;
// cout<<y<<" "<<c[y]<<endl ;
}
}
}
top = 0 ;
for( int i = 1 ; i <= n ; ++i ){
if( cd[i] == 0 && c[i] > 0 ){
a[++top].id = i ;
a[top].c = c[i] ;
}
}
sort( a+1 , a+1+top , cmp ) ;
if( top == 0 )
printf("NULL") ;
else{
for( int i = 1 ; i <= top ; ++i )
printf("%d %d\n" ,a[i].id ,a[i].c ) ;
}
return 0 ;
}
P1072 [NOIP2009 提高组] Hankson 的趣味题
暴力查就行 理论上会 t 但是好像数据比较水就暴力草过了
code:
#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b) {
if (a < b) swap(a, b);
return b == 0 ? a : gcd(b, a % b);
}
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
int a0, a1, b0, b1;
int ans = 0;
scanf("%d%d%d%d", &a0, &a1, &b0, &b1);
for (int i = 1; i * i <= b1; ++i) {
if (b1 % i == 0) {
int p = b1 / i;
if (i % a1 == 0 && gcd(i, a0) == a1 && lcm(i, b0) == b1) ++ans;
if (p == i) continue;
if (p % a1 == 0 && gcd(p, a0) == a1 && lcm(p, b0) == b1) ++ans;
}
}
printf("%d\n",ans);
}
return 0;
}
P1082 [NOIP2012 提高组] 同余方程
直接扩欧求解 解唯一 但是要注意负数取模问题
具体可以详见扩展欧几里得算法学习笔记
code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1;
y = 0;
return;
}
exgcd(b, a % b, x, y);
ll z = x;
x = y;
y = z - (a / b) * y;
}
int main() {
ll a, b, x, y;
scanf("%lld%lld", &a, &b);
exgcd(a, b, x, y);
x = (x + b) % b;
printf("%lld",x);
return 0;
}
P1253 扶苏的问题
线段树 但是要考虑一下两个 tag 的下传问题
我们发现当修改标记为空时 下传区间加标记
但如果不为空 那么子树中所有的区间加标记都作废
code:
#include <bits/stdc++.h>
#define int long long
#define ls (k << 1)
#define rs (k << 1 | 1)
#define mid ((l + r) >> 1)
using namespace std;
const int N = 5e6 + 0721;
int tr[N], a[N];
int pls[N], turn[N];
int n, q;
inline void pushup(int k) {
tr[k] = max(tr[ls], tr[rs]);
}
void build(int k, int l, int r) {
turn[k] = -1;
if (l == r) {
tr[k] = a[l];
return;
}
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(k);
// cout << k << " " << tr[k] << endl;
}
void pushdown(int k) {
if (turn[k] != -1) {
turn[ls] = turn[rs] = turn[k];
pls[ls] = pls[rs] = pls[k];
tr[ls] = tr[rs] = turn[k] + pls[k];
pls[k] = 0;
turn[k] = -1;
} else {
tr[rs] += pls[k];
tr[ls] += pls[k];
pls[ls] += pls[k];
pls[rs] += pls[k];
pls[k] = 0;
}
}
void modify1(int k, int l, int r, int s, int e, int x) {
if (l >= s && r <= e) {
tr[k] = x;
turn[k] = x;
pls[k] = 0;
return;
}
pushdown(k);
if (s <= mid) modify1(ls, l, mid, s, e, x);
if (e > mid) modify1(rs, mid + 1, r, s, e, x);
pushup(k);
}
void modify2(int k, int l, int r, int s, int e, int x) {
if (l >= s && r <= e) {
tr[k] += x;
pls[k] += x;
return;
}
pushdown(k);
if (s <= mid) modify2(ls, l, mid, s, e, x);
if (e > mid) modify2(rs, mid + 1, r, s, e, x);
pushup(k);
}
int query(int k, int l, int r, int s, int e) {
if (l >= s && r <= e) {
return tr[k];
}
pushdown(k);
int res = -0x7ffffffffffffff;
if (s <= mid) res = max(res, query(ls, l, mid, s, e));
if (e > mid) res = max(res, query(rs, mid + 1, r, s, e));
pushup(k);
return res;
}
signed main() {
ios::sync_with_stdio(false);
cin >> n >> q;
for (int i = 1; i <= n; ++i) cin >> a[i];
build(1, 1, n);
while (q--) {
int opt, l, r, x;
cin >> opt;
if (opt == 1) {
cin >> l >> r >> x;
modify1(1, 1, n, l, r, x);
} else if (opt == 2) {
cin >> l >> r >> x;
modify2(1, 1, n, l, r, x);
} else {
cin >> l >> r;
// cout<<l<<" "<<r<<endl;
// cout<<n<<" "<<l<<" "<<r<<endl;
cout << query(1, 1, n, l, r) << '\n';
}
}
return 0;
}
P1260 工程规划
纯查分约束板子 具体可以详见差分约束学习笔记
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 0721;
int head[N], nxt[N], to[N], len[N], cnt;
int dis[N], vis[N];
bool exist[N];
int n, m;
queue<int>q;
inline void cmb(int x, int y, int z) {
to[++cnt] = y;
len[cnt] = z;
nxt[cnt] = head[x];
head[x] = cnt;
}
bool spfa(int s) {
memset(dis, 0x3f, sizeof dis );
dis[s] = 0;
q.push(s);
exist[s] = 1;
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = head[now]; i; i = nxt[i]) {
int y = to[i];
if (dis[y] > dis[now] + len[i]) {
dis[y] = dis[now] + len[i];
if (!exist[y]) {
q.push(y);
exist[y] = 1;
}
vis[y] = vis[now] + 1;
if (vis[y] >= n) return 1;
}
}
exist[now] = 0;
}
return 0;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
cmb(y, x, z);
}
for (int i = 1; i <= n; ++i) cmb(0, i, 0);
if (spfa(0))
printf("NO SOLUTION");
else {
int minn = 0x7fffffff;
for (int i = 1; i <= n; ++i) minn = min(minn, dis[i]);
for (int i = 1; i <= n; ++i) printf("%d\n",dis[i] - minn);
}
return 0;
}
P1196 [NOI2002] 银河英雄传说
带权并查集板子 常看常新
code:
#include<bits/stdc++.h>
using namespace std ;
const int N = 30721 ;
int fa[N] , cnt[N] , tot[N] ;
int n ;
int find( int x ){
if( x == fa[x] )
return x ;
int fx = find(fa[x]) ;
cnt[x] += cnt[fa[x]] ;
return fa[x] = fx ;
}
int main () {
scanf("%d" ,&n ) ;
for( int i = 1 ; i <= 30000 ; ++i )
fa[i] = i , tot[i] = 1 ;
while( n-- ){
char c ;
int x , y ;
cin>>c ;
scanf("%d%d" ,&x ,&y ) ;
if( c == 'M' ){
int fx = find(x) , fy = find(y) ;
cnt[fx] += tot[fy] ;
fa[fx] = fy ;
tot[fy] += tot[fx] , tot[fx] = 0 ;
}
else{
int fx = find(x) , fy = find(y) ;
if( fx != fy )
printf("-1\n") ;
else
printf("%d\n" ,abs( cnt[x] - cnt[y] ) - 1 ) ;
}
}
return 0 ;
}

浙公网安备 33010602011771号