[置顶] Dear 时继

575人阅读 评论(2) 收藏 举报
分类:

NOIP模板整理

“愿我们的爱恨万古长存。”

“而我终将老去,如山间风,如花上露。”

基础部分

高精度

模拟版
//好丑QAQ

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 20005;
char a[MAXN],b[MAXN];
int ca[MAXN],cb[MAXN],cc[MAXN];
int lena,lenb;

void init(){
    memset(ca,0,sizeof(ca));
    memset(cb,0,sizeof(cb));
    memset(cc,0,sizeof(cc));
    for(int i = 0; i < lena; i ++)
        ca[i] = a[lena - i - 1] - '0';
    for(int i = 0; i < lenb; i ++)
        cb[i] = b[lenb - i - 1] - '0';
}

void jia(){
    init();int len = 0;
    while(len <= lena + 2 || len <= lenb){
        cc[len] += ca[len] + cb[len];
        cc[len + 1] += cc[len] / 10;
        cc[len] %= 10;len ++;
    }
    len += 3;
    while(true){
        if(cc[len] == 0) len --;
        else break;
    }
    if(len == 0){puts("0");return;}
    for(int i = len; i >= 0; i --)
        printf("%d",cc[i]);
}

void jian(){
    init();
    if(lena < lenb){
        for(int i = 0; i < lenb; i ++)
            swap(ca[i],cb[i]);
        printf("-");
    }
    else if(lena == lenb){
        for(int i = lena - 1; i >= 0; i --){
            if(ca[i] > cb[i]) break;
            else{
                for(int j = i; j >= 0; j --)
                    swap(ca[j],cb[j]);
                printf("-");
                break;
            }
        }
    }int len = 0;
    memset(cc,0,sizeof(cc));
    while(len <= lena + 2 || len <= lenb + 2){
        if(ca[len] < cb[len])
            ca[len] += 10,ca[len + 1] --;
        cc[len] += ca[len] - cb[len],len ++;
    }len += 3;
    while(true){
        if(cc[len] == 0) len --;
        else break;
    }
    if(len == 0){puts("0"); return;}
    for(int i = len; i >= 0; i --)
        printf("%d",cc[i]);
}

void cheng(){
    init(); int len = lena + lenb + 3;
    for(int i = 0; i <= lena + 3; i ++)
        for(int j = 0; j <= lenb + 3; j ++)
            cc[i + j] += ca[i] * cb[j];
    for(int i = 0; i <= len; i ++)
        cc[i + 1] += cc[i] / 10,cc[i] %= 10;
    while(true){
        if(cc[len] == 0) len --;
        else break;
    }
    if(len == 0){puts("0");return;}
    for(int i = len; i >= 0; i --)
        printf("%d",cc[i]);
}
/*
void gc(int b){
    bool flag = 0;
    for(int i = len; i >= 2; i --){
        ans[i - 1] += (ans[i] % b) * 10;
        ans[i] /= b;
        if(!flag){
            if(!ans[i]) len --;
            else flag = true;
        }
    }
    ans[1] /= b,ans[0] = len;
}
*/
int main(){
    cin >> a >> b;
    lena = strlen(a);
    lenb = strlen(b);
    jian();
    return 0;
}

结构体版

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = (2048 + 5) << 1;
struct bign{
    int len,num[MAXN];
    bool flag;
    bign(){len = 1;flag = 0;memset(num,0,sizeof(num));}
    bign(int x){
        if(!x)  return;
        len = 0;
        while(x){
            num[++ len] = x % 10;
            x /= 10;
        }
    }
};

bool operator < (bign a,bign b){
    if(a.len < b.len)   return 1;
    if(a.len > b.len)   return 0;
    for(int i = a.len; i >= 1; i --)
        if(a.num[i] > b.num[i])
            return false;
    return true;
}

bool operator == (bign a,bign b){
    if(a.len != b.len)  return false;
    for(int i = 1; i <= a.len ; i ++)
        if(a.num[i] != b.num[i])
            return false;
    return true;
}

bign operator + (bign &A,bign &B){
    bign ret;
    int i = 1,x = 0;
    while(i <= A.len || i <= B.len){
        ret.num[i] = A.num[i] + B.num[i] + x;
        x = ret.num[i] / 10;
        ret.num[i] %= 10;
        i ++;
    }
    ret.num[i] = x,ret.len = i;
    if(!ret.num[ret.len])   ret.len --;
    return ret;
}

bign operator - (bign a,bign b){
    bign ans;
    if(a == b)  return ans;
    if(b < a){
        for(int i = 1; i <= a.len;i ++){
            if(a.num[i] < 0){   
                a.num[i] += 10,a.num[i + 1] --;
            }
            ans.num[i] = a.num[i] - b.num[i];
            if(ans.num[i] < 0){ 
                ans.num[i] += 10,a.num[i + 1] --;//向a的高位借 
            }
        }
    }
    else{
        ans.flag = 1;//答案小于0
        for(int i = 1; i <= b.len; i ++){
            if(b.num[i] < 0){   
                b.num[i] += 10,b.num[i + 1] --;
            }
            ans.num[i] = b.num[i] - a.num[i];
            if(ans.num[i] < 0){
                ans.num[i] += 10,
                b.num[i + 1] --;//向b的高位借 
            }
        }   
    }
    int len = max(a.len,b.len);
    while(!ans.num[len] && len > 1) len --;
    ans.len = len;
    return ans;
}

bign operator * (bign a,bign b){
    bign ans;
    int len = a.len + b.len;
    for(int i = 1; i <= a.len; i ++){
        int x = 0;
        for(int j = 1; j <= b.len; j ++){
            ans.num[i + j - 1] += (a.num[i] * b.num[j] + x);
            x = ans.num[i + j -1] / 10;
            ans.num[i + j - 1]%= 10;
        }
        ans.num[i + b.len] += x;
    }
    while(!ans.num[len] && len > 1)  len --;
    ans.len = len;
    return ans;
}

bign get(){
    bign ans;string s;cin >> s;
    int lens = s.length();
    ans.len = lens;
    for(int i = 0; i < ans.len; i ++)
        ans.num[ans.len - i] = s[i] - 48;
    return ans;
}

void out(bign x){
    if(x.flag)  cout << "-";
    for(int i = x.len; i >= 1; i --)
        cout << x.num[i];
}

bign a,b;
int main(){
    a = get(),b = get();
    out(a - b);//这是减法 加减乘随便改
    return 0;
}

子集枚举

//这个并没有用二进制处理

void dms(){
    for(int i = 1; i <= n; i ++)
        if(used[i]) printf("%d ",num[i]);
    puts("");
}

void dfs(int now){
    if(now > n) {dms();return;}
    for(int i = 0; i <= 1; i ++){
        used[now] = i;
        dfs(now + 1);
        used[now] = false;
    }
}

归并&&逆序对

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 200005;
typedef long long LL;
int n,num[MAXN],ha[MAXN];
LL ans = 0;

void work(int l,int r){
    if(l == r) return;
    int mid = (l + r) >> 1;
    work(l,mid),work(mid + 1,r);

    int ll = l,rl = mid + 1,now = 1;
    while(ll <= mid && rl <= n){
        if(num[ll] > num[rl]){
            ha[now] = num[rl];
            now ++,rl ++,ans += mid - ll;
        }
        else 
            ha[now] = num[ll],now ++,ll ++;
    }
    while(ll <= mid){
        ha[now] = num[ll],ll ++,now ++;
    }
    while(rl <= n){
        ha[now] = num[rl],rl ++,now ++;
    }
    int ssr = r - l + 1;
    for(int i = 1; i <= ssr; i ++)
        num[l - 1 + i] = ha[i];
}

int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++)
        scanf("%d",&num[i]);
    work(1,n);
    printf("%lld\n",ans);
    return 0;
}

全排列

void dms(int x){
    if(x > 0){
        for(int i = 1; i <= n; i ++){
            if(used[i]) continue;
            used[i] = true;
            ans[x] = i;
            dms(x - 1);
            used[i] = false;
        }
    }
    else{
        for(int i = n; i >= 1; i --)
            printf("%d ",ans[i]);
        puts("");
    }
}

尺取法

int cqf(){
    int l = 0,r = 0,ans = 0,len = MAXN;
    while(true){
        while(r <= n && ans < S)
            r ++,ans += num[r];
        if(ans < S) break;
        len = min(len,r - l + 1);
        ans -= num[l ++];
    }
    return len < n ? len : -1;
} 

堆排

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 1000005;
int n,s,heap[MAXN],cnt = 0;
//小根堆 stl默认大根堆 
void pop(){
    heap[1] = heap[cnt];
    int p = 1;
    while(p * 2 + 1 <= cnt){
        int l = p * 2,r = p * 2 + 1;
        if(heap[l] < heap[p]){
            if(heap[r] < heap[l] && heap[r] < heap[p])
                swap(l,r);//!!!!
            swap(heap[l],heap[p]);p = l;
        }
        else if(heap[r] < heap[p])
            swap(heap[r],heap[p]),p = r;
        else     break;
    }
    cnt --;
}

void push(int x){
    cnt ++;int p = cnt;heap[p] = x;
    //顺序…… 
//  int l = p * 2,r = p * 2 + 1;
    while(p != 1){
        int f = p / 2;//!!!!!!
        if(heap[f] > heap[p])
            swap(heap[f],heap[p]),p = f;
        else    break;
    }
}

int main(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++)
        scanf("%d",&s),push(s);
    for(int i = 1; i <= n; i ++)
        printf("%d ",heap[1]),pop();
    return 0;
}

手动读入

inline int read(){
    char ch = getchar();int f = 1, x = 0;
    while(!(ch >= '0' && ch <= '9')){if(ch == '-')f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9') {x = x * 10 + (ch - '0');ch = getchar();}
    return x * f;
} 

⑧数码问题

爱情之路

数据结构

并查集

int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
bool same(int x,int y){return find(x) == find(y);}
void merge(int x,int y){
    x = find(x),y = find(y);
    if(deep[x] > deep[y])   swap(x,y);
    fa[x] = y;
    if(deep[x] == deep[y])  deep[y] ++;
}

树状数组

int lowbit(int x){return x & (-x);}
void add(int x,int y){
    while(x <= n){tree[x] += y,x += lowbit(x);}
}

int sum(int x){
    int s = 0;
    while(x)    {s += tree[x],x -= lowbit(x);}
    return s;
}
int answer(int x,int y){return sum(y) - sum(x - 1);}

int num[MAXN];
int main(){
    memset(tree,0,sizeof(tree));
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++)
        scanf("%d",&num[i]),add(i,num[i] - num[i - 1]);
    scanf("%d",&m);
    for(int j = 1; j <= m; j ++){
        scanf("%d",&t);
        if(t == 1){
            scanf("%d %d %d",&a,&b,&y);
            add(a,y),add(b + 1,-y);
        }
        else if(t == 2)
            scanf("%d",&y),printf("%d\n",sum(y));
    }
    return 0;
}

线段树

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define L(x) (x << 1)       //左儿子
#define R(x) (x << 1 | 1)   //右儿子
#define sz(x) (tree[x].r - tree[x].l + 1)   //区间长度
const int MAXN = 200005;
typedef long long ll;
using namespace std;
ll n,a,b,x,q,z,t,y,num[MAXN];
struct tree{
    ll l,r,sum,add;      //左,右,和,加
}tree[MAXN << 2];

void update(ll p){//标记清空
    tree[p].sum = tree[L(p)].sum + tree[R(p)].sum;
}

void spread(ll p){//标记下放
    if(!tree[p].add)    return;
    tree[L(p)].add += tree[p].add;
    tree[R(p)].add += tree[p].add;
    tree[L(p)].sum += tree[p].add * sz(L(p));
    tree[R(p)].sum += tree[p].add * sz(R(p));
    tree[p].add = 0;    update(p);
}

void build(ll l,ll r,ll p){
    tree[p].l = l,tree[p].r = r,tree[p].add = 0;
    if(l == r){//如果相等则无儿子
        tree[p].sum = num[l];
        return;
    }   
    ll mid = (tree[p].l + tree[p].r) >> 1;
    build(l,mid,L(p)),build(mid + 1,r,R(p));
    update(p);
}

void change(ll l,ll r,ll p,ll v){//修改
    if(l <= tree[p].l && tree[p].r <= r){
        tree[p].add += v;
        tree[p].sum += v * sz(p);
        return;
    }
    spread(p);
    ll mid = (tree[p].l + tree[p].r) >> 1;
    if(l <= mid)    change(l,r,L(p),v);
    if(mid < r)    change(l,r,R(p),v);
    update(p);
} 

ll ask(ll l,ll r,ll p){//查询
    if(l <= tree[p].l && tree[p].r <= r)    return tree[p].sum;
    spread(p);
    ll mid = (tree[p].l + tree[p].r) >> 1,ans = 0;
    if(l <= mid)    ans += ask(l,r,L(p));
    if(mid < r)    ans += ask(l,r,R(p));
    update(p);  return ans;
}

int main(){
    memset(num,0,sizeof(num));
    scanf("%lld",&n);
    for(int i = 1; i <= n; i ++)    
        scanf("%lld",&num[i]);
    build(1,n,1);   scanf("%lld",&q);
    for(ll i = 1; i <= q; i ++){
        scanf("%lld",&t);
        if(t == 1){
            scanf("%lld %lld %lld",&a,&b,&x);
            change(a,b,1,x);
        }
        else if(t == 2){
            scanf("%lld %lld",&y,&z);
            printf("%lld\n",ask(y,z,1));
        }
    }
    return 0;
}

图论

货车运输

玛丽卡

1.最短路

floyd

void floyd(){
    for(int k = 1; k <= n; k ++)
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
}

spfa_slf

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 200005;
int n,m,s,e,f,t,v,tot = 0,cnt;
int first[MAXN],nxt[MAXN],dis[MAXN];
bool used[MAXN];

struct edge{
    int f,t,v;
}l[MAXN];

void build(int f,int t,int v){
    l[++ tot] = (edge){f,t,v};
    nxt[tot] = first[f];
    first[f] = tot;
}

deque < int > q;
void spfa(int s){
    while(!q.empty()) q.pop_front();
    memset(used,0,sizeof(used));
    memset(dis,0x3f,sizeof(dis));
    dis[s] = 0,used[s] = true;
    q.push_front(s);cnt = dis[0];

    while(!q.empty()){
        int u = q.front();q.pop_front();
        used[u] = false;
        for(int i = first[u]; i != -1; i = nxt[i]){
            int w = l[i].t;
            if(dis[w] > dis[u] + l[i].v){
                dis[w] = dis[u] + l[i].v;
                if(used[w]) continue;
                if(q.empty()) q.push_front(w);
                else if(dis[w] < dis[q.front()]) q.push_front(w);
                else q.push_back(w); 
            }
        }
    }
}

int main(){
    memset(first,0xff,sizeof(first));
    scanf("%d %d %d %d",&n,&m,&s,&e);
    for(int i = 1; i <= m; i ++){
        scanf("%d %d %d",&f,&t,&v);
        build(f,t,v);build(t,f,v);
    }
    spfa(s);
    if(dis[e] == cnt) puts("-1");
    else printf("%d\n",dis[e]);
    return 0;
}

dij_heap

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 200005;
int n,m,s,e,f,t,v,tot = 0;
int first[MAXN],nxt[MAXN],ans = 0;
bool used[MAXN];
struct edge{
    int f,t,v;
}l[MAXN];

struct zt{
    int u,v;
    bool operator < (const zt &b)const {
        return v > b.v;
    }
};
priority_queue < zt > q;
void build(int f,int t,int v){
    l[++ tot] = (edge){f,t,v};
    nxt[tot] = first[f];
    first[f] = tot;
}

int dij(int s,int e){
    memset(used,0,sizeof(used));
    while(!q.empty()) q.pop();
    q.push((zt){s,0});
    while(!q.empty()){
        zt us = q.top(); q.pop();
        int u = us.u;
        if(u == e) return us.v;
        if(used[u]) continue;
        used[u] = true;
        for(int i = first[u]; i != -1; i = nxt[i]){
            int w = l[i].t,rs = us.v + l[i].v;
            q.push((zt){w,rs});
        }
    }
    return -1;
}

int main(){
    memset(first,0xff,sizeof(first));
    scanf("%d %d %d %d",&n,&m,&s,&e);
    for(int i = 1; i <= m; i ++){
        scanf("%d %d %d",&f,&t,&v);
        build(f,t,v);build(t,f,v);
    }
    ans = dij(s,e);printf("%d\n",ans);
    return 0;
}

2.最小生成树

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 20005;
int n,f,t,v,tot = 0,fa[MAXN],deep[MAXN];
struct edge{
    int f,t,v;
}l[MAXN];
int find(int x){return  x == fa[x] ? x : fa[x] = find(fa[x]);}
bool same(int x,int y){return find(x) == find(y);}
bool cmp(edge a,edge b){return a.v < b.v;}
void init(){
    memset(deep,0,sizeof(deep));
    for(int i = 1; i <= n; i ++)    fa[i] = i;
}

void merge(int x,int y){
    x = find(x),y = find(y);
    if(deep[x] > deep[y])   swap(x,y);
    fa[x] = y;
    if(deep[x] == deep[y]) deep[y] ++;
}

int kru(){
    int ans = 0;
    sort(l + 1,l + tot + 1,cmp);
    for(int i = 1; i <= tot; i ++)
        if(!same(l[i].f,l[i].t))
            ans += l[i].v,merge(l[i].f,l[i].t);
    return ans;
}

int main(){
    scanf("%d",&n);init();
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++){
            scanf("%d",&v);
            if(i == j) continue;
            tot ++;
            l[tot].f = i,l[tot].t = j,l[tot].v = v;
        }
    printf("%d\n",kru());
    return 0;   
}

3.次短路

deque < int > q;
void spfa_slf(int s){
    memset(dis,0x3f,sizeof(dis));
    memset(pre,0x3f,sizeof(pre));
    memset(used,0,sizeof(used));
    used[s] = true,dis[s] = 0;
    q.push_back(s);

    while(!q.empty()){
        int u = q.front();q.pop_front();
        used[u] = false;
        for(int i = first[u];i != -1; i = next[i]){
            int w = l[i].t;
            if(dis[w] > dis[u] + l[i].v){
                pre[w] = dis[w];
                dis[w] = dis[u] + l[i].v;
                if(used[w]) continue;
                if(q.empty()) q.push_front(w);
                else if(dis[w] < dis[q.front()])    q.push_front(w);
                else    q.push_back(w);
                used[w] = true;

            }
//如果可以更新最短路,那么就让它更新吧
//更新后的最短路是最短路,更新之前的最短路是当前的次短路
            else if(pre[w] > dis[u] + l[i].v && dis[w] < dis[u] + l[i].v){
                pre[w] = dis[u] + l[i].v;
                if(used[w]) continue;
                if(q.empty()) q.push_front(w);
                else if(dis[w] < dis[q.front()])    q.push_front(w);
                else    q.push_back(w);
                used[w] = true;
            }
//如果不能更新最短路,但是可以更新次短路,那么就让它更新吧
            else if(pre[w] > pre[u] + l[i].v){
                pre[w] = pre[u] + l[i].v;
                if(used[w]) continue;
                if(q.empty()) q.push_front(w);
                else if(dis[w] < dis[q.front()])    q.push_front(w);
                else    q.push_back(w);
                used[w] = true;
            } 
//次短路可以更新次短路,那么就让它更新吧
        }
    }
}

4.K短路

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 200005;
int first[MAXN],next[MAXN],tot = 0;
int n,m,s,t,K,f,t,v,h[MAXN],dis[MAXN];
bool use[MAXN];
struct edge{
    int f,t,v;
}l[MAXN];
struct zt{
    int u,v;
    bool operator < (const int &b) const{
        return v + h[u] > b.v + h[b.u];
    }
};
priority_queue < zt > q;
void build(int f,int t,int v){
    l[++ tot] = (edge){f,t,v};
    next[tot] = first[f];
    first[f] = tot;
}

void dij(int s){
    memset(dis,0x3f,sizeof(dis));
    dis[s] = 0;q.push((zt){s,0});
    while(!q.empty()){
        zt x = q.top(); p.pop();
        int u = x.u;
        for(int i = first[u]; i != -1; i = next[i]){
            int w = l[i].t;
            if(dis[w] > dis[u] + l[i].v){
                dis[w] = dis[u] + l[i].v;
                q.push((zt){w,dis[w]});
            }
        }
    }
}

int dij_k(int s,int e,int k){
    if(s == e) k ++;
    q.push((zt){s,0});
    while(!q.empty()){
        zt x = q.top();q.pop();int u = x.u;
        if(u == e){
            k --;
            if(k == 0)  return x.v;
        }
        for(int i = first[u]; i != -1; i = next[i]){
            int w = l[i].t,c = x.v + l[i].v;
            q.push((zt){w,c});
        }
    }
    return -1;
}

5.LCA

void make_tree(int x,int f,int v){
    deep[x] = deep[f] + 1;
    fa[x][0] = f;rank[x] = v;
    for(int i = first[x]; i != -1; i = next[i])
        if(l[i].t != f) make_tree(l[i].t,x,v + l[i].v);
}

void make_lca(){
    for(int j = 1; j <= log2(n); j ++)
        for(int i = 1; i <= n; i ++)
            fa[i][j] = fa[fa[i][j - 1]][j - 1];
}

int lca(int x,int y){
    if(deep[x] < deep[y]) swap(x,y);
    for(int i = log2(n); i >= 0; i --)
        if(deep[fa[x][i]] >= deep[y])
            x = fa[x][i];
    if(x == y)  return x;
    for(int i = log2(n); i >= 0; i --)
        if(fa[x][i] != fa[y][i])
            x = fa[x][i],y = fa[y][i];
    return fa[x][0];
}

int main(){
    memset(first,0xff,sizeof(first));
    scanf("%d",&n);
    for(int i = 1; i < n; i ++){
        scanf("%d %d %d",&f,&t,&v);
        build(f,t,v),build(t,f,v);
    }
    make_tree(0,n,0),make_lca();
    scanf("%d",&m);
    for(int i = 1; i <= m; i ++){
        scanf("%d %d",&f,&t);
        printf("%d\n",rank[f] + rank[t] - (rank[lca(f,t)] << 1));
    }
    return 0;
}

6.二分图染色

queue < int > q;
int work(int s){
    while(!q.empty()) q.pop();
    int cnt1 = 0,cnt2 = 0;
    used[s] = true;color[s] = 1;q.push(s);

    while(!q.empty()){
        int u = q.front();q.pop();
        if(color[u] == 1) cnt1 ++;
        else    cnt2 ++;
        for(int i = first[u]; i != -1; i = next[i]){
            int w = l[i].t;
            if(!used[w]){
                color[w] = 1 - color[u];
                used[w] = true;q.push(w);
            }
            else
                if(color[w] == color[u])    return -1;
        }
    }
    return ans += min(cnt1,cnt2);
}

7.Tarjan

int first[MAXN],next[MAXN],low[MAXN],dfn[MAXN];
int scc_num,dfs_clock,scc[MAXN];
stack < int > s;

int dfs(int u){
    low[u] = dfn[u] = ++ dfs_clock;s.push(u);
    for(int i = first[u]; i != -1; i = next[i]){
        int w = l[i].t;
        if(!dfn[w])
            dfs(w),low[u] = min(low[w],low[u]);
        else if(!scc[w])    low[u] = min(low[u],dfn[w]);
    }
    if(low[u] == dfn[u]){
        scc_num ++;
        while(true){
            int x = s.top();s.pop();
            scc[x] = scc_num;
            if(x == u)  break;
        }
    }
}

8.dfs找环

void dfs(int x){
    int k = x,cnt = 0;
    while(true){
        times[x] = cnt ++,used[x] = k,x = t[x];
        if(used[x] > 0){
            if(used[x] == k){
                ans = min(ans,cnt - times[x]);
                break;
            }       
            else{ans = ans;break;}   
        }
    }
}

int main(){
    memset(t,0,sizeof(t));
    memset(used,0,sizeof(used));
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++)    scanf("%d",&t[i]);
    for(int i = 1; i <= n; i ++)    if(used[i] == 0)    dfs(i);
    printf("%d\n",ans);
    return 0;
}

9.拓扑排序

void topsort(){
    for(int i = 1; i <= n; i ++)    if(!rudu[i])   q.push(i);
    while(!q.empty()){
        int u = q.front();q.pop();printf("%d ",u);
        for(int i = first[i]; i != -1; i = next[i]){
            int w = l[i].t; rudu[w] --;
            if(!rudu[w])  q.push(w);
        }
    }
} 

void init(){
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++){
        while(true){
            scanf("%d",&x);
            if(x == 0) break;
            build(i,x); rudu[x] ++;
        }
    }
}

数论

int gcd(int a, int b){
    // a > b
    if(b == 0) return a;
    return gcd(b,a % b);
}

int lcm(int x, int y){
    int c =  x * y / gcd(x,y);
    return c;
}

int exgcd(int a, int b, int &x, int &y){
    // a > b
    if(b == 0) {x = 1,y = 0;return a;}
    int ans = gcd(b,a % b,x,y);
    int w = x; x = y;
    y = w - a / b * y;
    return ans;
}

bool used[MAXN];
void Eular_find_prime(){
    for(int i = 2; i <= n; i ++){
        if(used[i] == 0)    prime[++ cnt] = i;
        for(int j = 1; j <= cnt && prime[j] * i <= n; j ++){
            used[prime[j] * i] = 1;
            if(i % prime[j] == 0)   break;
        }
    }
}

void Erato_find_prime(){
     for(int i = 2; i <= n; i ++)   if(!used[i])        
            for(int j = i + i; j <= n; j += i)  used[j] = 1;
    for(int i = 2; i <= n; i ++)
        if(!used[i])    printf("%d ", i);
    puts("");
}

int ksm(int a,int b){
    if(b == 0)  return 1;
    int ans = 1;
    while(b){
        if(b & 1)   ans *= a;
        a *= a;b >>= 1;
    }
    return ans;
}


int FTA(int n){   //唯一分解定理 
    tot = 0;    
    for(int i = 2;i <= n;i ++)    {    
        while(n % i == 0){num[tot ++] = i;n /= i;    }    
    }    
    for(int i = 0;i < c;i ++)    
        printf(i == 0 ? "%d" : "*%d" ,num[i]);    
    puts("");   return 0;    
}    

动态规划

背包

void zopack(int vi,int wi){
    // 01背包 
    for(int i = v - vi; i >= 0; i --)
        dp[i + vi] = max(dp[i + vi],dp[i] + wi);
}

void wqpack(int vi,int wi){
    //完全背包
    for(int i = 0; i <= v - vi; i ++)
        dp[i + vi] = max(dp[i + vi],dp[i] + wi);
}

void dcpack(int vi,int wi,int num){
    if(vi * num > v)    wqpack(vi,wi);
    int k = 1;
    while(k < num){
        zopack(vi * k,wi * k);
        num -= k,k <<= 1;
    }
    zopack(vi * num,wi * num);
}

int main(){
    scanf("%d %d",&n,&v);
    for(int i = 1; i <= n; i ++){
        scanf("%d %d %d",&viv,&w,&num);
        if(num < 0)     wqpack(viv,w);
        else    dcpack(viv,w,num);
    }
    for(int i = 0; i <= v; i ++)ans = max(ans,dp[i]);
    printf("%d\n",ans); return 0;
} 

最长严格上升子序列

int where(int x){
    /*寻找x在g中的下标 即以x为最小结尾的子序列长度*/
    int l = 1,r = n;
    while(l <= r){
        int mid = (l + r) >> 1;
        if(g[mid] == x)         return mid;
        else if(g[mid] < x)     l = mid + 1;
        else if(g[mid] > x)     r = mid - 1;
    }
    return l;
}

int dpdpd(){
    memset(g,0x3f,sizeof(g));//极大值 
    int len = 0;
    /*
        对于原序列中每一个数,寻找g中下标
        并用这个数更新g数组与长度 
    */ 
    for(int i = 1; i <= n; i ++){
        int j = where(num[i]);
        g[j] = min(g[j],num[i]);
        len = max(len,j);
    }
    return len;
}

石子归并

int main(){
    memset(dp,0x3f,sizeof(dp)); 
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++){
        scanf("%d",&x);
        sum[i] = sum[i - 1] + x;
        dp[i][i] = 0;
    }
    for(int i = n - 1; i >= 1; i --)
        for(int j = i + 1; j <= n; j ++)
            for(int k = i; k <= j - 1; k ++)
                dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]);
    printf("%d\n",dp[1][n]);
    return 0;
}

树形

没有上司的舞会

图上

伊吹萃香

环形

void dpdpd(){
    memset(dp,0,sizeof(dp));
    int k = n << 1;
    for(int i = 2; i <= k; i ++)
        for(int j = i - 1; j >= 1 && i - j < n; j --)
            for(int r = j; r < i; r ++)
                dp[j][i] = max(dp[j][i],dp[j][r] + dp[r + 1][i] + num[j] * num[r + 1] * num[i + 1]),ans = max(ans,dp[j][i]);
    printf("%d\n",ans);
}

套路QAQ

传纸条&&方格取数……

void dpdpd(){
    for(int i = 1; i <= m ; i ++)
        for(int j = 1; j <= n; j ++)
            for(int x = 1; x <= m; x ++)
                for(int y = 1; y <= n; y ++){
                    if(i == x || j == y)
                        dp[i][j][x][y] = max(max(dp[i - 1][j][x - 1][y],dp[i][j - 1][x][y - 1]),max(dp[i][j - 1][x - 1][y],dp[i - 1][j][x][y - 1])) + map[i][j];
                    else
                        dp[i][j][x][y] = max(max(dp[i - 1][j][x - 1][y],dp[i][j - 1][x][y - 1]),max(dp[i][j - 1][x - 1][y],dp[i - 1][j][x][y - 1])) + map[i][j] + map[x][y];
                }
}

拦截导弹

int main(){
    memset(num,0,sizeof(num));
    while(scanf("%d",&num[++ n]) != EOF);
    //输入处理 
    n --;
    for(int i = n - 1; i >= 0; i --){
        for(int j = i; j <= n; j ++)
            if(num[i] < num[j])
                up[i] = max(up[i],up[j] + 1);

        for(int j = i; j <= n; j ++)
            if(num[i] > num[j])
                down[i] = max(down[i],down[j] + 1);
    }
    for(int i = 0; i <= n; i ++){
        maxs = max(up[i],maxs);
        mins = max(down[i],mins);
    }
    printf("%d\n%d",mins + 1,maxs);
    return 0;
}

尼克的任务

输出第一个

void dpdpd(){
    int ds = k;
    for(int i = n; i >= 1; i --){
        if(num[ds].l == i){//有>= 1的任务
            while(num[ds].l == i){
                if(dp[i] < dp[i + num[ds].t])
                    dp[i] = dp[i + num[ds].t];
                ds --;
            }   
        } 
        else if(num[ds].l != i)//没有任务 
            dp[i] = dp[i + 1] + 1;
    }
}
查看评论

精选优美英文短文1——Dear Basketball(亲爱的篮球)

北京时间2018年3月5日,今天举行的奥斯卡颁奖典礼上,科比凭借《亲爱的篮球》获得最佳动画短片奖。Dear basketball                       Kobe BryantDe...
  • Vinsuan1993
  • Vinsuan1993
  • 2018-03-05 15:32:25
  • 108

Too Dear for the Whistle

As i grew up , came into the world, and observed the actions of men, i thought i met with many, who ...
  • aweirl
  • aweirl
  • 2004-09-20 18:56:00
  • 1218

28 Five pounds too dear五磅也太贵

Why was even five pounds 'too dear'? Small boats loaded with wares sped to the great liner as she w...
  • fengyan5022
  • fengyan5022
  • 2015-12-16 10:13:47
  • 340

虚表~

虚表(vtable)一直都好像很神秘的样子,今天工作中涉及到虚表,就做下一些记录吧~ 1.每一个拥有虚函数的类都有一个虚表,注意是虚函数。 2.虚表实际上是一个函数指针数组,记录了本类所有虚函数的...
  • guaren0118
  • guaren0118
  • 2013-04-05 15:44:09
  • 551

DEAR

DEAR
  • qq_39447313
  • qq_39447313
  • 2017-10-14 18:16:11
  • 40

科比:Dear Basketball(写给篮球的一封信)

科比:Dear Basketball(写给篮球的一封信)   Kobe Bryant   Dear Basketball, 亲爱的篮球,   From the moment 从小时候   I ...
  • u012942555
  • u012942555
  • 2016-01-16 17:46:49
  • 538

Thank you letter

Photo Credit: Copyright Alison Doyle The following is an example of a thank you letter email ...
  • screaming
  • screaming
  • 2016-06-07 23:33:15
  • 456

无线路由器密码忘记应对策略

无线路由器密码忘记应对策略 分步阅读     为了防止别人随意修改我们的路由器设置,我们一般都会设置修改路由器登陆密码!那么如果我们自己忘记了怎么办呢,本文教你怎么重置登陆密码并备份设置防止再次遗忘!...
  • dear_Alice_moon
  • dear_Alice_moon
  • 2015-09-02 17:29:37
  • 672

Dear diary moment

开始写 Blog,不知道能坚持多久。想起《老友记》里的一个情节:有个调酒师约Monica出去的时候,Chandler不失时机地讽刺一句说:“oh, this is a dear-diary-momen...
  • dustindwind
  • dustindwind
  • 2009-08-25 00:07:00
  • 516

ios开发之 App加紧审核

有时候,App发布后发生重大的BUG,造成用户使用过程中经常崩溃;又或者遭遇病毒的侵蚀(例如最近的XcodeGhost事件),公司往往会第一时间提交一个新的安全版本,如果按照往常,大概审核需要一周时间...
  • shiyunjiangnan
  • shiyunjiangnan
  • 2015-09-25 15:21:59
  • 405
    个人资料
    等级:
    访问量: 7万+
    积分: 2881
    排名: 1万+
    %%%