# 基础题

## #1.1 1085 背包问题

01背包模板

``` 1 #include<cstdio>
2 #include<iostream>
3 using namespace std;  4
5 int n,maxx,DP[1000000],w,v;  6
7 int main(){  8     scanf("%d%d",&n,&maxx);  9
10     for(int i = 1;i <= n;i++){ 11         scanf("%d%d",&w,&v); 12         for(int j = maxx;j >= w;j--) 13             DP[j] = max(DP[j],DP[j-w]+v); 14  } 15
16     cout << DP[maxx]; 17
18     return 0; 19 }```
01背包 + 一维表示

## #1.2 1086 背包问题 V2

``` 1 #include<cstdio>
2 #include<iostream>
3 using namespace std;  4
5 int n,maxx,DP[1000000],w,v,c;  6
7 int main(){  8     scanf("%d%d",&n,&maxx);  9
10     for(int i = 1;i <= n;i++){ 11         scanf("%d%d%d",&w,&v,&c); 12         int d = 1; 13         while(d <= c){ 14             for(int j = maxx;j >= d*w;j--) 15                 DP[j] = max(DP[j],DP[j-d*w]+d*v); 16             c -= d; 17             d *= 2; 18         }for(int j = maxx;c && j >= c*w;j--) 19             DP[j] = max(DP[j],DP[j-c*w]+c*v); 20  } 21
22     cout << DP[maxx]; 23
24     return 0; 25 }```

## #1.3 1257 背包问题 V3

``` 1 #include<stdio.h>
2 #include<math.h>
3 #include<iostream>
4 #include<algorithm>
5 using namespace std;  6
7 int n,k;  8 long long ansv,answ;  9
10 double eps = 0.000000001; 11
12 struct data{ 13     long long w,v; 14     double vrw; 15 }arr[1000000]; 16
17 bool cmp(const data &a,const data &b){ return a.vrw > b.vrw; } 18
19 bool check(long long &sumv,long long &sumw,double line){ 20     for(int i = 1;i <= n;i++) 21         arr[i].vrw = 1.0*arr[i].v-line*arr[i].w; 22
23     sort(arr+1,arr+1+n,cmp); 24
25     double tmp = 0; 26     sumv = 0,sumw = 0; 27     for(int i = 1;i <= k;i++) 28         sumv += arr[i].v, 29         sumw += arr[i].w, 30         tmp += arr[i].vrw; 31
32     return tmp >= 0; 33 } 34
35 long long gcd(long long a,long long b){ 36     if(a < b) swap(a,b); 37     return !b?a:gcd(b,a%b); 38 } 39
40 int main(){ 41
42     scanf("%d%d",&n,&k); 43
44     for(int i = 1;i <= n;i++) 45         scanf("%lld%lld",&arr[i].w,&arr[i].v); 46
47     double L = 0,R = 1000000; 48     long long sumv,sumw; 49     while(R-L > eps){ 50 // printf("%.8lf %.8lf\n",L,R);
51         double mid = (L+R)/2; 52         if(check(sumv,sumw,mid)) ansv = sumv, answ = sumw, L = mid; 53         else R = mid; 54  } 55
56     long long d = gcd(ansv,answ); 57     printf("%lld/%lld",ansv/d,answ/d); 58
59     return 0; 60 }```

## #2.1 1136 欧拉函数

Emmmm，现在有 m 与 p 互质且 p 为质数，那么 phi( p ) = p-1 ，phi( mp ) = phi( m )*phi( p ) = phi( m )*( p-1 )

Emmmm 这个我居然没法证明

``` 1 #include<stdio.h>
2 #include<iostream>
3 using namespace std;  4
5 //int prime[100000],primesize;  6 //bool isprime[100000];  7 //void getlist(int listsize){  8 // listsize = (int)sqrt(listsize)+10;  9 // isprime[ 10 //}
11
12 int phi(int &x){ 13     int ans = 1; 14     for(int i = 2;i*i <= x;i++){ 15         if(x%i) continue; 16         ans *= (i-1); 17         x /= i; 18         while(x%i == 0){ 19             ans *= i; 20             x /= i; 21  } 22     }if(x > 1) ans *= x-1; // 这条和 i*i <= x 可以防止x为大质数导致TLE
23     return ans; 24 } 25
26 int main(){ 27     int n; 28     scanf("%d",&n); 29
30     cout << phi(n); 31
32     return 0; 33 }```

## #3.1 1242 斐波那契数列的第N项

``` 1 #include<cstdio>
2 #include<iostream>
3 #define mod 1000000009
4 using namespace std;  5
6 struct MAT{  7     long long d[5][5];  8     MAT(){ d[1][1] = d[1][2] = d[2][1] = d[2][2] = 0; }  9     void Init(){ 10         d[1][2] = d[2][1] = d[2][2] = 1; 11         d[1][1] = 0; 12  } 13 }I; 14
15 MAT mul(MAT A,MAT B){ 16  MAT C; 17     for(int i = 1;i <= 2;i++) 18         for(int j = 1;j <= 2;j++) 19             for(int k = 1;k <= 2;k++) 20                 C.d[i][j] = (C.d[i][j]+A.d[i][k]*B.d[k][j]%mod)%mod; 21     return C; 22 } 23
24 MAT ksm(MAT A,long long k){ 25     MAT B = A; 26     k--; 27     while(k){ 28         if(k&1) B = mul(B,A); 29         A = mul(A,A); 30         k >>= 1; 31     }return B; 32 } 33
34 int main(){ 35     long long n; 36     scanf("%lld",&n); 37
38     if(n <= 2) return printf("1"),0; 39
40  MAT I; 41  I.Init(); 42
43     I = ksm(I,n-1); 44
45     long long c = (I.d[1][1]+I.d[1][2])%mod; 46
47     cout << c; 48
49     return 0; 50 }```

## #4 1106 质数检测

Miller-Rabbin 素性测试，二次探测才是核心

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define LL long long
4 using namespace std;
5
6 int prime[8] = {2,3,5,7,11,13,17,19};
7
8 LL ksm(LL x,LL k,LL m){
9     if(k == 1) return x%m;
10     if(!k) return 1;
11     LL b = 1;
12     while(k){
13         if(k&1) b = b*x%m;
14         x = x*x%m;
15         k >>= 1;
16     }return b%m;
17 }
18
19 bool TD(LL x,LL a){
20     if(x == a) return true;
21     LL m = x-1;
22     while(m % 2 == 0) m >>= 1;
23     LL t = ksm(a,m,x);
24     while(m != x-1 && t != 1 && t != x-1)
25         t = t*t%x,m <<= 1;
26     return (m&1 || t == x-1);
27 }
28
29 bool isPrime(LL x){
30     if(x == 2) return true;
31     if(x < 1 || x % 2 == 0) return false;
32     for(int i = 0;i < 8;i++)
33         if(!TD(x,prime[i])) return false;
34     return true;
35 }
36
37 int main(){
38     int n;
39     scanf("%d",&n);
40
41     for(int i = 1;i <= n;i++){
42         long long x; scanf("%lld",&x);
43         if(isPrime(x)) printf("Yes\n");
44         else printf("No\n");
45     }
46
47     return 0;
48 }```
Miller Rabbin

## #5 1088 最长回文子串

Hash+二分，具体请看这里：

``` 1 #include<stdio.h>
2 #include<iostream>
3 #include<cstring>
4 #define maxn 421357
5 #define base 21707
6 #define ULL unsigned long long
7 using namespace std;
8
10
11 int n,ans = 1,lens; char s[maxn];
12
13 ULL Pow(ULL x,int k){
14     if(!k) return 1;
15     if(k == 1) return x;
16     ULL b = 1;
17     while(k){
18         if(k&1) b = b*x;
19         x = x*x;
20         k >>= 1;
21     }return b;
22 }
23
24 ULL getcode(int L,int R){
27 }
28
29 ULL getanti(int L,int R){
30     if(R == n) return anti[L];
31     else return anti[L]-anti[R+1]*Pow(base,R-L+1);
32 }
33
34 int find(int pos){
35     int L = 0,R = min(lens-1-pos,pos),mid;
36     while(L < R){
37         mid = (L+R+1)/2;
38 //        printf("Checking... [%d , %d]\n",pos-mid,pos+mid);
39 //        ULL cntcode = (getanti(pos+1,pos+mid)*base+s[pos])*Pow(base,mid)+getcode(pos+1,pos+mid);
40         if(getcode(pos-mid,pos-1) == getanti(pos+1,pos+mid)) L = mid;
41         else R = mid-1;
42     }return L*2+1;
43 }
44
45 int exfind(int pos){
46     if(pos == lens-1) return 0;
47     int L = 0,R = min(lens-1-pos,pos+1),mid;
48     while(L < R){
49         mid = (L+R+1)/2;
50 //        printf("Checking... [%d , %d]\n",pos-mid,pos+mid);
51 //        ULL cntcode = (getanti(pos+1,pos+mid)*base+s[pos])*Pow(base,mid)+getcode(pos+1,pos+mid);
52         if(getcode(pos-mid+1,pos) == getanti(pos+1,pos+mid)) L = mid;
53         else R = mid-1;
54     }return L*2;
55 }
56
57 int main(){
58     scanf("%s",s);
59     lens = strlen(s);
60
61     ULL cntcode = 0;
62     for(int i = 0;i < lens;i++)
63         cntcode = cntcode*base+s[i],
65
66     cntcode = 0;
67     for(int i = lens-1;i >= 0;i--)
68         cntcode = cntcode*base+s[i],
69         anti[i] = cntcode;
70
71     for(int pos = 0;pos < lens;pos++)
72         ans = max(ans,find(pos)),
73         ans = max(ans,exfind(pos));
74     cout << ans;
75
76     return 0;
77 }```
Hash+二分

# 3级算法题

## #1 1267 4个数和为0

Hash+加强的check函数

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define ULL unsigned long long
4 #define maxn 1000007
5 using namespace std;
6
7 struct data{ ULL val,pos; }sum[maxn];
8 int m,n,arr[maxn];
9
10 struct edge{ ULL val,pos; int from; }e[maxn*4];
11 int tot,first[maxn];
12
13 bool noequ(ULL A,ULL B){
14     return (A/10000 != B/10000) && (A%10000 != B%10000);
15 }
16
17 bool check(ULL val,ULL pos){
18     int w = val%maxn;
19     for(int i = first[w];i;i = e[i].from){
20         if(e[i].val == val && noequ(e[i].pos,pos)) return true;
21     }return false;
22 }
23
24 void insert(int pos1,int pos2,int suuum){
25     if(pos1 > pos2) swap(pos1,pos2);
26     ULL val = (ULL)(suuum+1e9);
27     ULL kcode = pos1*10000+pos2;
28
29     if(check(val,kcode)) return;
30
31     int w = val%maxn;
32
33     tot++; e[tot].from = first[w];
34     e[tot].val = val; e[tot].pos = kcode;
35     first[w] = tot;
36     sum[++m].val = val;
37     sum[m].pos = kcode;
38 }
39
40 int main(){
41     scanf("%d",&n);
42
43     for(int i = 1;i <= n;i++)
44         scanf("%d",&arr[i]);
45
46     for(int i = 1;i <= n;i++)
47         for(int j = i+1;j <= n;j++)
48             insert(i,j,arr[i]+arr[j]);
49
50 //    for(int i = 1;i <= m;i++) printf("%I64u %I64u\n",sum[i].val,sum[i].pos);
51 //
52 //    cout << "Hash:" << endl;
53 //
54 //    for(int i = 1;i <= tot;i++) printf("%I64u %I64u\n",e[i].val,e[i].pos);
55
56     for(int i = 1;i <= m;i++){
57         if(check(2e9-sum[i].val,sum[i].pos)){
58             cout << "Yes";
59             return 0;
60         }
61     }
62
63     cout << "No";
64
65     return 0;
66 }```
Hash+补丁

# 4级算法题

## #1 1113 矩阵快速幂

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define LL long long
4 using namespace std;  5
6 LL mod = 1000000007;  7 int n,k;  8
9 struct mat{ 10     LL d[200][200]; 11 // mat(){ for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) d[i][j] = 0; }
12 }; 13
14 mat mul(mat &A,mat &B){ 15  mat C; 16     for(int i = 1;i <= n;i++){ 17         for(int j = 1;j <= n;j++){ 18             C.d[i][j] = 0; 19             for(int k = 1;k <= n;k++) 20                 C.d[i][j] = (C.d[i][j]+A.d[i][k]*B.d[k][j])%mod; 21  } 22     }return C; 23 } 24
25 mat ksm(mat &A,int k){ 26 // cout<<k<<endl;
27     if(k == 1) return A; 28 // cout<<k<<endl;
29     mat B = A; k--; 30     while(k){ 31 // cout<<k<<endl;
32         if(k&1) B = mul(B,A); 33         A = mul(A,A); 34         k >>= 1; 35     }return B; 36 } 37
38 int main(){ 39     scanf("%d%d",&n,&k); 40
41  mat ans; 42     for(int i = 1;i <= n;i++) 43         for(int j = 1;j <= n;j++) 44             scanf("%lld",&ans.d[i][j]); 45
46     ans = ksm(ans,k); 47 // return 233;
48
49     for(int i = 1;i <= n;i++){ 50         for(int j = 1;j <= n;j++) 51             printf("%lld ",ans.d[i][j]%mod); 52         cout << endl; 53  } 54
55     return 0; 56 }```

## #2 1051 最大子矩阵和

Emmmmmm 解法比较坑（说明我的基础已经被steam腐蚀殆尽了qwq）

``` 1 #include<stdio.h>
2 #include<iostream>
3 using namespace std;  4
5 int n,m;  6 long long cnt,ans,sum[505][505] = {0};  7
8 int main(){  9     scanf("%d%d",&m,&n); 10
11     for(int i = 1;i <= n;i++){ 12         for(int j = 1;j <= m;j++){ 13             scanf("%lld",&sum[i][j]); 14             sum[i][j] += sum[i-1][j]; 15  } 16  } 17
18 // for(int i = 1;i <= n;i++){ 19 // for(int j = 1;j <= m;j++) 20 // printf("%lld ",sum[i][j]); 21 // printf("\n"); 22 // }
23
24     for(int up = 0;up <= n-1;up++){ 25         for(int dw = up+1;dw <= n;dw++){ 26             cnt = 0; 27             for(int i = 1;i <= m;i++){ 28                 cnt = max(cnt+sum[dw][i]-sum[up][i],sum[dw][i]-sum[up][i]); 29                 ans = max(ans,cnt); 30 // if(cnt+(sum[dw][i]-sum[up][i]) < 0){ 31 // ans = max(ans,cnt); cnt = 0; 32 // }else cnt += sum[dw][i]-sum[up][i]; 33 // printf("#[%d-%d]%d: %lld\n",up,dw,i,cnt);
34  } 35 // ans = max(ans,cnt);
36  } 37     }printf("%lld",ans); 38
39     return 0; 40 }```

## #3 1287 加农炮

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define mid (L+R)/2
4 #define lc (rt<<1)
5 #define rc (rt<<1|1)
6 #define maxn 1000000
7 using namespace std;  8
9 int n,m,connon; 10
11 struct node{ 12     int maxx; 13 }; 14
15 struct SegmentTree{ 16     int qL,qR,val,pos; 17     node T[maxn*4]; 18
19     void build(int rt,int L,int R){ 20         if(L == R){ scanf("%d",&T[rt].maxx); } 21         else{ 22             build(lc,L,mid); build(rc,mid+1,R); 23             T[rt].maxx = max(T[lc].maxx,T[rc].maxx); 24  } 25  } 26
27     int query(int rt,int L,int R){ 28         if(L == R) return L; 29         else{ 30             if(val <= T[lc].maxx) return query(lc,L,mid); 31             else if(val <= T[rc].maxx) return query(rc,mid+1,R); 32             else return 0; 33  } 34  } 35
36     void modify(int rt,int L,int R){ 37         if(L == R) T[rt].maxx++; 38         else{ 39             if(pos <= mid) modify(lc,L,mid); 40             else modify(rc,mid+1,R); 41             T[rt].maxx = max(T[lc].maxx,T[rc].maxx); 42  } 43  } 44
45     void print(int rt,int L,int R){ 46         if(L == R) printf("%d ",T[rt].maxx); 47         else{ print(lc,L,mid); print(rc,mid+1,R); } 48  } 49
50     void Print(){ print(1,1,n); } 51
52     void Build(){ build(1,1,n); } 53
54     int Query(int heigh){ val = heigh; return query(1,1,n); } 55
56     void Modify(int Emmm){ pos = Emmm; modify(1,1,n); } 57 }A; 58
59 int main(){ 60     scanf("%d%d",&n,&m); 61
62  A.Build(); 63
64     for(int i = 1;i <= m;i++){ 65         scanf("%d",&connon); 66         int pos = A.Query(connon); 67         if(pos <= 1) continue; 68         A.Modify(pos-1); 69  }A.Print(); 70
71     return 0; 72 }```

## #4 1463 找朋友

``` 1 #include<stdio.h>
2 #include<iostream>
3 #include<algorithm>
4 #define mid (L+R)/2
5 #define lc (rt << 1)
6 #define rc (rt<<1|1)
7 #define maxn 1000000
8 using namespace std;  9
10 int arr[maxn],brr[maxn],cnt,bos[maxn],sto[maxn],k[maxn],n,m,q; 11
12 struct node{ 13     int maxx; 14 }T[maxn*4]; 15
16 void build(int rt,int L,int R){ 17     if(L == R) T[rt].maxx = arr[L]; 18     else{ 19         build(lc,L,mid); build(rc,mid+1,R); 20         T[rt].maxx = max(T[lc].maxx,T[rc].maxx); 21  } 22 } 23
24 void modify(int rt,int L,int R,int pos,int val){ 25     if(L == R) T[rt].maxx = val,sto[pos] = val; 26     else{ 27         if(pos > R || pos < 1) return; 28         if(pos <= mid) modify(lc,L,mid,pos,val); 29         else modify(rc,mid+1,R,pos,val); 30         T[rt].maxx = max(T[lc].maxx,T[rc].maxx); 31  } 32 } 33
34 int query(int rt,int L,int R,int qL,int qR){ 35     if(qL <= L && R <= qR) return T[rt].maxx; 36     else{ 37         int ans = 0; 38         if(qL <= mid) ans = max(ans,query(lc,L,mid,qL,qR)); 39         if(qR > mid) ans = max(ans,query(rc,mid+1,R,qL,qR)); 40         return ans; 41  } 42 } 43
44 struct ask{ 45     int from,L,R,ans,ord; // first[R]
46 }e[maxn]; 47 int tot,first[maxn]; 48 void insert(int L,int R,int ord){ 49     tot++; 50     e[tot].ord = ord, 51     e[tot].L = L, 52     e[tot].R = R, 53     e[tot].from = first[R]; 54     first[R] = tot; 55 } 56
57 bool cmp(const ask &A,const ask &B){ return A.ord < B.ord; } 58
59 int main(){ 60     scanf("%d%d%d",&n,&q,&m); 61
62     for(int i = 1;i <= n;i++) scanf("%d",&arr[i]); 63     for(int i = 1;i <= n;i++) scanf("%d",&brr[i]),bos[brr[i]] = i; 64     for(int i = 1;i <= m;i++) scanf("%d",&k[i]); 65
66     for(int i = 1;i <= q;i++){ 67         int L,R; 68         scanf("%d%d",&L,&R); 69  insert(L,R,i); 70  } 71
72 // printf("#bos: "); for(int i = 1;i <= n;i++) printf("%d ",bos[i]); cout << endl;
73
74     for(int i = 2;i <= n;i++){ 75         for(int j = 1;j <= m;j++){ 76             int ppos = bos[brr[i]-k[j]]; //printf("~#%d: ppos %d i-k[j] %d\n",brr[i],ppos,i-k[j]);
77             if(ppos >= 1 && ppos < i && sto[ppos] < arr[ppos]+arr[i]) 78                 modify(1,1,n,ppos,arr[ppos]+arr[i]); 79             ppos = bos[brr[i]+k[j]]; //printf("~#%d: ppos %d i-k[j] %d\n",brr[i],ppos,i-k[j]);
80             if(ppos >= 1 && ppos < i && sto[ppos] < arr[ppos]+arr[i]) 81                 modify(1,1,n,ppos,arr[ppos]+arr[i]); 82         }for(int p = first[i];p;p = e[p].from){ 83             e[p].ans = query(1,1,n,e[p].L,e[p].R); 84         }//printf("#%d: ",i); for(int j = 1;j <= n;j++) printf("%d ",sto[j]); cout << endl;
85     }sort(e+1,e+1+tot,cmp); 86
87     for(int i = 1;i <= tot;i++) printf("%d\n",e[i].ans); 88
89     return 0; 90 }```

## #5 1076 2条不相交的路径

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define maxn 2000000
4 using namespace std;
5
6 int dfn[maxn],low[maxn],TIM,s[maxn],poi,color[maxn],COL,n,m,q;
7
8 struct edge{ int from, u, v; }e[maxn];
9 int tot,first[maxn]; void insert(int u,int v){
10     tot++; e[tot].from = first[u]; e[tot].v = v; e[tot].u = u; first[u] = tot;
11 }
12
13 void dfs(int u,int fa){
14 //    printf("Now deep in #%d\n",u);
15     dfn[u] = low[u] = ++TIM;
16     s[poi++] = u;
17     for(int i = first[u];i;i = e[i].from){
18         int v = e[i].v; if(!dfn[v]){
19 //            printf("#%d; get in Poi B\n",u);
20             dfs(v,u); low[u] = min(low[u],low[v]);
21         }else if(dfn[v] < dfn[u] && v != fa) low[u] = min(low[u],dfn[v]);
22     }//printf("#%d: get in poi A\n",u);
23
24     if(low[u] == dfn[u]){
25 //        printf("#%d get the first!\n",u);
26         color[u] = ++COL;
27         while(s[poi-1] != u && poi){
28             poi--; color[s[poi]] = COL;
29         }if(poi) poi--;
30     }
31 }
32
33 int main(){
34     scanf("%d%d",&n,&m);
35
36     for(int i = 1;i <= m;i++){
37         int u,v; scanf("%d%d",&u,&v);
38         insert(u,v); insert(v,u);
39     }for(int i = 1;i <= n;i++)
40         if(!color[i]) dfs(i,i);
41
42 //    for(int i = 1;i <= n;i++) printf("%d ",color[i]); cout << endl;
43
44     scanf("%d",&q);
45
46     for(int i = 1;i <= q;i++){
47         int u,v; scanf("%d%d",&u,&v);
48         if(color[u] == color[v]) printf("Yes\n");
49         else printf("No\n");
50     }
51
52
53
54
55     return 0;
56 }```
Tarjan求强联通

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define maxn 1000000
4 using namespace std;
5
6 int dfn[maxn],low[maxn],TIM,COL,color[maxn],n,m,q;
7 bool iscut[2*maxn],buck[maxn*2];
8
9 struct edge{ int from,u,v,bri; }e[maxn*2];
10 int tot,first[maxn]; void insert(int u,int v){
11     tot++; e[tot].bri = 0; e[tot].u = u; e[tot].from = first[u]; e[tot].v = v; first[u] = tot;
12 }
13
14 void dfs(int u,int fa){ // To tag the bri
15     dfn[u] = low[u] = ++TIM;
16     int child = 0;
17     for(int i = first[u];i;i = e[i].from){
18         int v = e[i].v; //if(v == fa) continue;
19         if(v != fa) child++;
20         if(!dfn[v]){
21             dfs(v,u);
22             low[u] = min(low[u],low[v]);
23             if(low[v] >= dfn[u]) iscut[u] = true;
24         }else if(dfn[v] < dfn[u] && v != fa) low[u] = min(low[u],dfn[v]);
25     }if(fa == u && child > 1) iscut[u] = false;
26 //    printf("#%d: child %d iscut %d\n",u,child,iscut[u]);
27 }
28
29 void tagg(){
30     for(int i = 1;i <= tot;i++)
31         if(iscut[e[i].u] && iscut[e[i].v])
32             e[i].bri = 1, buck[i] = true;
33 }
34
35 void dfs1(int u,int fa){
36     color[u] = COL;
37     for(int i = first[u];i;i = e[i].from){
38         if(e[i].v == fa || buck[i] || color[e[i].v]) continue;
39         dfs1(e[i].v,u);
40     }
41 }
42
43 int main(){
44 //    freopen("16.txt","r",stdin);
45 //    freopen("16.out","w",stdout);
46
47     scanf("%d%d",&n,&m);
48
49     for(int i = 1;i <= m;i++){
50         int u,v; scanf("%d%d",&u,&v);
51         insert(u,v); insert(v,u);
52     }for(int i=1;i<=n;i++)if(!dfn[i])
53     dfs(i,i); for(int i = 1;i <= n;i++)
54         if(!e[first[i]].from) iscut[i] = true;
55 //    for(int i = 1;i <= n;i++) printf("%d ",iscut[i]); cout << endl;
56     tagg();
57
58 //    for(int i = 1;i <= tot;i++) printf("#%d:%d->%d \$%d\$\n",i,e[i].u,e[i].v,buck[i]);
59 //    for(int i = 1;i <= n;i++) printf("%d ",color[i]); cout << endl;
60
61     for(int i = 1;i <= n;i++)
62         if(!color[i]){ ++COL; dfs1(i,i); }
63
64     scanf("%d",&q);
65
66     for(int i = 1;i <= q;i++){
67         int u,v; scanf("%d%d",&u,&v);
68         if(color[u] == color[v]) printf("Yes\n");
69         else printf("No\n");
70     }
71
72     return 0;
73 }```

# 5级算法题

## #1 1494 选举拉票

Orz 这道题，当真是思考题

``` 1 #include<stdio.h>
2 #include<queue>
3 #include<algorithm>
4 #include<iostream>
5 #define mid (L+R)/2
6 #define lc (rt<<1)
7 #define rc (rt<<1|1)
8 #define maxn 200000
9 using namespace std; 10
11 long long n,list[maxn],qwq; 12 bool vis[maxn]; 13
14 struct nodd{ 15     long long num,sum; 16 }T[maxn*4]; 17
18 void modify(long long rt,long long L,long long R,long long pos,long long val){ 19     if(pos < L || pos > R) return; 20     if(L == R) T[rt].num += val,T[rt].sum += val*pos; 21     else{ 22         /*if(pos <= mid)*/ modify(lc,L,mid,pos,val); 23         /*else*/ modify(rc,mid+1,R,pos,val); 24         T[rt].num = T[lc].num+T[rc].num; 25         T[rt].sum = T[lc].sum+T[rc].sum; 26  } 27 } 28
29 long long query(long long rt,long long L,long long R,long long pos){ 30     if(pos <= 0) return 0; 31     if(pos > T[rt].num) return 2e9; 32     if(L == R) return L*pos;//T[rt].sum;
33     else if(pos <= T[lc].num) return query(lc,L,mid,pos); 34     else return T[lc].sum + query(rc,mid+1,R,pos-T[lc].num); 35 } 36
37 priority_queue<long long,vector<long long> ,greater<long long> > heap[maxn]; 38
39 bool cmp1(long long A,long long B){ return heap[A].size() > heap[B].size(); } 40
41 int main(){ 42     scanf("%lld",&n); 43
44     for(int i = 1;i <= n;i++){ 45         long long x,y; 46         scanf("%lld%lld",&x,&y); 47  heap[x].push(y); 48         if(x&&!vis[x]) list[++qwq] = x,vis[x] = true; 49         if(x) modify(1,0,20000,y,1); 50  } 51
52     sort(list+1,list+1+qwq,cmp1); 53 // cout << "list"; 54 // for(int i = 1;i <= qwq;i++) printf("%d ",list[i]); cout << endl;
55     long long s = heap[0].size(),num = 0,sum = 0,ans = 2e9; 56
57     for(int i = n;i >= max(1LL,s);i--){ 58         for(int j = 1;j <= qwq;j++){ 59             if(heap[list[j]].size() < i) break; 60             while(heap[list[j]].size() >= i){ 61                 sum += heap[list[j]].top(); 62                 modify(1,0,20000,heap[list[j]].top(),-1); 63  heap[list[j]].pop(); 64                 num++; 65  } 66         }ans = min(ans,sum+query(1,0,20000,i-(num+s))); 67 // printf("#%d: ans %d\n",i,ans);
68  } 69
70     printf("%lld",ans); 71
72     return 0; 73 }```

## #2 1199 Money out of Thin Air

```  1 #include<stdio.h>
2 #include<iostream>
3 #define mid (L+R)/2
4 #define lc (rt<<1)
5 #define rc (rt<<1|1)
6 #define maxn 1000000
7 #define LL long long
8 using namespace std;
9
10 int dfn[maxn],dfl[maxn],TIM,sz[maxn],fa[maxn],n,m;
11 LL vval[maxn],arr[maxn],ans[maxn];
12
13 struct edge{
14     int from,v;
15 }e[maxn]; int tot,first[maxn];
16 void insert(int u,int v){ tot++; e[tot].from = first[u]; e[tot].v = v; first[u] = tot; }
17
18 void dfs(int u){
19     dfn[u] = ++TIM;
20     arr[TIM] = vval[u];
21     sz[u] = 1;
22     for(int i = first[u];i;i = e[i].from){
23         int v = e[i].v;
24         dfs(v);
25         sz[u] += sz[v];
26     }dfl[u] = TIM;
27 }
28
29 struct node{
30     LL sum,lazy;
31 }T[maxn*4];
32
33 void pushdown(int rt,int L,int R){
34     if(!T[rt].lazy) return;
35     T[lc].lazy += T[rt].lazy;
36     T[rc].lazy += T[rt].lazy;
37     T[lc].sum += T[rt].lazy*(mid-L+1);
38     T[rc].sum += T[rt].lazy*(R-mid);
39     T[rt].lazy = 0;
40 }
41
42 void build(int rt,int L,int R){ // 1,1,TIM
43     if(L == R) T[rt].sum = arr[L];
44     else{
45         build(lc,L,mid); build(rc,mid+1,R);
46         T[rt].sum = T[lc].sum+T[rc].sum;
47     }
48 }
49
50 LL query(int rt,int L,int R,int qL,int qR){
51     pushdown(rt,L,R);
52     if(qL <= L && R <= qR) return T[rt].sum;
53     else{
54         LL ret = 0;
55         if(qL <= mid) ret += query(lc,L,mid,qL,qR);
56         if(qR > mid) ret += query(rc,mid+1,R,qL,qR);
57         return ret;
58     }
59 }
60
61 void modify(int rt,int L,int R,int qL,int qR,LL val){
62     pushdown(rt,L,R);
63     if(qL <= L && R <= qR){
64         T[rt].sum += val*(R-L+1);
65         T[rt].lazy += val;
66     }else{
67         if(qL <= mid) modify(lc,L,mid,qL,qR,val);
68         if(qR > mid) modify(rc,mid+1,R,qL,qR,val);
69         T[rt].sum = T[lc].sum + T[rc].sum;
70     }
71 }
72
73 void print(int rt,int L,int R){
74     pushdown(rt,L,R);
75     if(L == R) ans[L] = T[rt].sum;
76     else{
77         print(lc,L,mid);
78         print(rc,mid+1,R);
79     }
80 }
81
82 void final(){
83     for(int i = 1;i <= n;i++) printf("%lld\n",ans[dfn[i]]);
84 }
85
86 int main(){
87 //    freopen("1.in","r",stdin);
88
89     scanf("%d%d",&n,&m);
90
91     for(int i = 2;i <= n;i++){
92         scanf("%d%lld",&fa[i],&vval[i]);
93         insert(fa[i]+1,i);
94 //        insert(fa[i],i);
95     }
96
97     dfs(1);
98     build(1,1,TIM);
99
100     for(int i = 1;i <= m;i++){
101         char ctr; int x; LL z; double y;
102         cin >> ctr; scanf("%d%lf%lld",&x,&y,&z);
103
104         x++;
105         if(ctr == 'A'){
106             LL sum = query(1,1,TIM,dfn[x],dfl[x]);
107             if(1.0*sum/(dfl[x]-dfn[x]+1) < y) modify(1,1,TIM,dfn[x],dfl[x],z);
108         }else if(1.0*query(1,1,TIM,dfn[x],dfn[x]) < y) modify(1,1,TIM,dfn[x],dfn[x],z);
109 //        cout << "BBB" << endl;
110     }
111
112     print(1,1,TIM);
113     final();
114
115     return 0;
116 }```
DFS序+线段树

## #3 1378 夹克老爷的愤怒

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define maxn 1000000
4 using namespace std;
5
6 int DP[maxn][5],buoy[maxn],anch[maxn],depth[maxn],sz[maxn],n,k;
7
8 struct edge{
9     int from,v;
10 }e[maxn*2]; int tot,first[maxn];
11 void insert(int u,int v){ tot++; e[tot].from = first[u]; e[tot].v = v; first[u] = tot; }
12
13 void dfs(int u,int pre){
14     int sum = 0; sz[u] = 1;
15     DP[u][0] = DP[u][1] = 0; buoy[u] = 1e9; anch[u] = -1e9;
16     for(int i = first[u];i;i = e[i].from){
17         int v = e[i].v; if(v == pre) continue;
18         depth[v] = depth[u]+1;
19         dfs(v,u);
20         sz[u] += sz[v];
21         buoy[u] = min(buoy[u],buoy[v]);
22         anch[u] = max(anch[u],anch[v]);
23         sum += DP[v][0];
24     }
25
26     if(sz[u] == 1){
27         DP[u][1] = 1;
28         DP[u][0] = 0;
29         if(!k) DP[u][0] = 1;
30         buoy[u] = anch[u] = depth[u];
31         return;
32     }
33
34 //    printf("#%d: buoy%d anch%d\n",u,buoy[u],anch[u]);
35     if(anch[u]-depth[u] >= k){ // Must set
36 //        printf("#%d: Poi A\n",u);
37         DP[u][0] = DP[u][1] = sum+1;
38         buoy[u] = depth[u]-k;
39         anch[u] = buoy[u]-1;
40     }else if(2*depth[u]-buoy[u] < anch[u]){ // Can choose
41 //        printf("#%d: Poi B\n",u);
42         DP[u][0] = sum;
43         DP[u][1] = sum+1;
44     }else{ // Needn't
45 //        printf("#%d: Poi C\n",u);
46         DP[u][0] = DP[u][1] = sum;
47         anch[u] = buoy[u]-1;
48     }
49 }
50
51 int main(){
52     scanf("%d%d",&n,&k);
53
54     for(int i = 1;i < n;i++){
55         int u,v; scanf("%d%d",&u,&v);
56         u++,v++; insert(u,v); insert(v,u);
57     }depth[1] = 1;
58
59     dfs(1,1);
60
61     printf("%d\n",DP[1][1]);
62
63 //    for(int i = 1;i <= n;i++){
64 //        printf("#%d: 0:%d 1:%d buoy:%d anch:%d\n",i,DP[i][0],DP[i][1],buoy[i],anch[i]);
65 //    }
66
67     return 0;
68 }```

## #4 1424 零树

DP[ u ][ 1/0 ]：1和0分别表示到这个点需要增加和减少的操作次数

= =

``` 1 #include<stdio.h>
2 #include<iostream>
3 #define maxn 1000000
4 #define heng(x) (x<0?(-x):x)
5 using namespace std;
6
7 long long DP[maxn][5],val[maxn],n;
8
9 struct edge{
10     int from,v;
11 }e[maxn*2]; int first[maxn],tot;
12 void insert(int u,int v){ tot++; e[tot].from = first[u]; e[tot].v = v; first[u] = tot; }
13
14 void dfs(int u,int pre){
15     DP[u][0] = DP[u][1] = 0;
16 //    if(val[u] < 0) DP[u][0] = -val[u],DP[u][1] = 0;
17 //    else DP[u][0] = 0,DP[u][1] = val[u];
18
19     for(int i = first[u];i;i = e[i].from){
20         int v = e[i].v; if(v == pre) continue;
21         dfs(v,u);
22         DP[u][0] = max(DP[u][0],DP[v][0]);
23         DP[u][1] = max(DP[u][1],DP[v][1]);
24     }int del = DP[u][1]-DP[u][0]+val[u];
25     DP[u][del<0] += heng(del);
26 }
27
28 int main(){
29     scanf("%lld",&n);
30     for(int i = 1;i < n;i++){
31         int u,v; scanf("%d%d",&u,&v);
32         insert(u,v); insert(v,u);
33     }for(int i = 1;i <= n;i++) scanf("%lld",&val[i]);
34
35     dfs(1,1);
36
37
38     printf("%lld",DP[1][0]+DP[1][1]);
39
40     return 0;
41 }```