各種模板總結

  • 數據結構
    • 線段樹
    • 樹鏈剖分 √
    • Treap
    • Splay
    • 左偏堆
    • 劃分樹 待添加
  • 字符串
    • KMP
    • MANACHER
    • 字典樹
    • 01字典樹 √
    • AC自動機 √
    • 後綴數組 √
    • 迴文樹 √
  • 數論
    • 矩陣快速冪 待添加
  • 圖論
    • 最短路(Dijkastra)待添加
    • 最短路(Floyd)待添加
    • 最短路(SPFA)待添加
    • 最小生成樹(Prim) 待添加
    • 最小生成樹(Kurskal) 待添加
  • 計算幾何
    • 掃描線 √
  • 其他
    • 大整數模板 √
    • 快速輸入模板 (整數) √
    • 快速輸入模板 (實數) √
    • 1~MOD的逆元 √
  • -

樹鏈剖分

const int maxn = 100000 + 5;        //樹中節點個數


//邊集
struct Edge{
    int v,pre,c;
}Es[maxn * 2];
int head[maxn],TOT_EDGE;
void INIT_EDGE(){                   //邊集初始化
    memset(head,-1,sizeof head);
    TOT_EDGE = 0;
}
void ADD_EDGE(int u,int v,int c){   //添加邊
    Es[TOT_EDGE].v = v;
    Es[TOT_EDGE].c = c;
    Es[TOT_EDGE].pre = head[u];
    head[u] = TOT_EDGE++;
}

/**樹鏈剖分部分*/
/**
**  son:    節點重兒子
**  fa:     節點父節點
**  dep:    節點在樹中深度
**  size:   節點子樹的大小
**  top:    節點在重鏈中的深度最低節點(最高節點)
**  tid:    節點編號(hash值)
**  RANK:   RANK[v]編號爲v的是第RANK[v]節點
**  SegSize:用於編號的迭代輔助變量,最小編號爲SegSize的初始值
*/
int son[maxn],fa[maxn],dep[maxn],size[maxn];
int top[maxn],tid[maxn],RANK[maxn],SegSize;
int DFS(int rt){
    dep[rt] = dep[fa[rt]] + 1;
    son[rt] = 0;
    size[rt] = 1;
    for(int i = head[rt];~i;i = Es[i].pre){
        int v = Es[i].v;
        if(v != fa[rt]){
            fa[v] = rt;
            size[rt] += DFS(v);
            if(size[son[rt]] < size[v]) son[rt] = v;
        }
    }
    return size[rt];
}
void Split(int rt,int tp){
    top[rt] = tp;
    tid[rt] = ++SegSize;
    RANK[tid[rt]] = rt;
    if(son[rt]){
        Split(son[rt],tp);
        for(int i = head[rt];~i;i = Es[i].pre){
            int v = Es[i].v;
            if(v != fa[rt] && v != son[rt]) Split(v,v);
        }
    }
}
void TreeLineSplit(){       //開始剖分
    dep[0] = 0;
    size[0] = 0;
    fa[1] = 0;
    DFS(1);
    SegSize = -1;
    Split(1,1);
}

Treap

/**
**  ch:節點的孩子節點
**  fa:夫節點
**  fix;優先級
**  size:當前子樹的大小
**  tot:節點個數(包括sroot)
**  sroot:超級根節點
**  key:節點的鍵值
*/
const int maxn = 15000 + 50,INF = 0x7fffffff;
int ch[maxn][2],fa[maxn],fix[maxn],size[maxn];
int tot,root,sroot;
int key[maxn];


/**
**  Treap初始化
*/
void Treap_Init(){
    tot = 1;
    root = sroot = 0;
    ch[sroot][0] = ch[sroot][1] = 0;
    fa[sroot] = 0;
    size[sroot] = 0;
    fix[sroot] = key[sroot] = INF;
}

/**
**  新建一個父節點爲FA,鍵值爲k的節點,返回節點編號
**
*/
int NewNode(int FA,int k){
    ch[tot][0] = ch[tot][1] = 0;
    fa[tot] = FA;
    size[tot] = 1;
    fix[tot] = rand();
    key[tot] = k;
    return tot++;
}

/**
**  更新rt的size信息
*/
void PushUp(int rt){ size[rt] = size[ch[rt][0]] + size[ch[rt][1]] + 1; if(rt == sroot) size[rt] = 0;}

/**
**  旋轉操作
**  kind:   0.表示rt爲fa[rt]的左孩子 進行右旋操作 zig
**  kind:   1.表示rt爲fa[rt]的右孩子 進行左旋操作 zag
*/
void rotate(int rt,int kind){
    int prt = fa[rt];
    ch[prt][kind] = ch[rt][!kind];fa[ch[rt][!kind]] = prt;
    ch[fa[prt]][ch[fa[prt]][1] == prt] = rt;fa[rt] = fa[prt];
    ch[rt][!kind] = prt;fa[prt] = rt;
    PushUp(prt);PushUp(rt);
}

/**
**  在根爲rt的樹中插入鍵值爲K的元素 這裏可以重複鍵值
*/
void Insert(int rt,int k){
    while(ch[rt][k >= key[rt]]) rt = ch[rt][k >= key[rt]];
    ch[rt][k >= key[rt]] = NewNode(rt,k);
    rt = ch[rt][k >= key[rt]];
    while(fa[rt] != sroot && fix[rt] > fix[fa[rt]]) rotate(rt,ch[fa[rt]][1] == rt);
    if(fa[rt] == sroot) root = rt;
    while(fa[rt] != sroot){
        rt = fa[rt];PushUp(rt);
    }
}

/**
**  刪除鍵值爲k的節點,使用前要保證一定有鍵值爲k的節點
*/
void Delete(int rt,int k){
    if(key[rt] == k){
        if(ch[rt][0] && ch[rt][1]){
            int nrt = ch[rt][0];
            if(fix[nrt] < fix[ch[rt][1]]) nrt = ch[rt][1];
            rotate(nrt,ch[rt][1] == nrt);
            Delete(rt,k);PushUp(nrt);
        }
        else{
            int nrt = ch[rt][0];
            if(nrt == sroot) nrt = ch[rt][1];
            ch[fa[rt]][ch[fa[rt]][1] == rt] = nrt;fa[nrt] = fa[rt];
        }
    }
    else{
        Delete(ch[rt][k >= key[rt]],k);
        PushUp(rt);
    }
}

/**
**  在rt的樹中查找鍵值第k小的節點 返回節點編號
*/
int Search(int rt,int k){
    if(k <= size[ch[rt][0]]) return Search(ch[rt][0],k);
    else if(k > size[ch[rt][0]] + 1) return Search(ch[rt][1],k - 1 - size[ch[rt][0]]);
    else return rt;
}

/**
**  查找鍵值爲k的節點在樹中是第幾小的
*/
int getRank(int rt,int k){
    if(rt == sroot) return 0;
    if(k >= key[rt]) return size[ch[rt][0]] + 1 + getRank(ch[rt][1],k);
    else return getRank(ch[rt][0],k);
}

Splay

/** ---- SPLAY ---- **/
/**  ch     邊
 **  fa     父節點
 **  size   子樹大小
 **  key    關鍵字大小
 **  tot    總共節點的個數
 **  root   當前的樹根
 **  sroot  超級根節點
**/
int ch[maxn][2],fa[maxn],size[maxn];
int key[maxn],pos[maxn];
int tot,root,sroot;

/** 初始化 */
void Splay_Init(){
    tot = 1;
    root = sroot = 0;
    ch[0][0] = ch[0][1] = 0;
    fa[0] = 0;
    key[0] = INF;
    size[0] = 0;
}

/** 新建一個節點 */
int NewNode(int FA,int k,int p){
    ch[tot][0] = ch[tot][1] = 0;
    fa[tot] = FA;
    size[tot] = 1;
    key[tot] = k,pos[tot] = p;
    return tot++;
}

/** 更新當前子樹的大小 和 根節點保留的信息 */
void PushUp(int rt){size[rt] = 1 + size[ch[rt][0]] + size[ch[rt][1]];}


/** 節點的旋轉操作
**  kind 0 表示rt爲fa[rt]的左孩子
**  kind 1 表示rt爲fa[rt]的右孩子
**  kind 0 進行zig 1 進行zag
*/
void rotate(int rt,int kind){
    int prt = fa[rt];
    ch[prt][kind] = ch[rt][!kind];fa[ch[rt][!kind]] = prt;
    ch[fa[prt]][ch[fa[prt]][1] == prt] = rt;fa[rt] = fa[prt];
    ch[rt][!kind] = prt;fa[prt] = rt;
    PushUp(prt);PushUp(rt);
}

/** 將rt節點 伸展至goal的孩子節點 */
void Splay(int rt,int goal){
    while(fa[rt] != goal){
        if(fa[fa[rt]] == goal) rotate(rt,ch[fa[rt]][1] == rt);
        else{
            int prt = fa[rt],kind = (ch[fa[prt]][1] == prt);
            if(ch[prt][kind] == rt) rotate(rt,kind),rotate(rt,kind);
            else rotate(rt,!kind),rotate(rt,kind);
        }
    }
    if(fa[rt] == sroot) root = rt;
}

/** 在根爲rt的樹內,插入關鍵字爲k的節點 */
void Insert(int rt,int k,int p){
    while(ch[rt][k > key[rt]]) rt = ch[rt][k > key[rt]];
    rt = (ch[rt][k > key[rt]] = NewNode(rt,k,p));
    Splay(rt,sroot);
}

/** 在根爲rt的樹內,查找關鍵字爲k的節點 */
int Find(int rt,int k){
    while(ch[rt][k >= key[rt]])
        if(k == key[rt]) return rt;
        else rt = ch[rt][k >= key[rt]];
    return sroot;
}

/** 查找關鍵字爲k 的前驅 */
int Find_Pre(int rt,int k){
    rt = Find(rt,k);
    Splay(rt,sroot);
    if(ch[rt][0] == sroot) return sroot;
    else rt = ch[rt][0];
    while(ch[rt][1]) rt = ch[rt][1];
    return rt;
}

/** 查找關鍵字爲k 的後繼 */
int Find_Next(int rt,int k){
    rt = Find(rt,k);
    Splay(rt,sroot);
    if(ch[rt][1] == sroot) return sroot;
    else rt = ch[rt][1];
    while(ch[rt][0]) rt = ch[rt][0];
    return rt;
}

01字典樹

const int maxn = 100000 + 5;        //集合中的數字個數
typedef long long LL;
int ch[32 * maxn][2];               //節點的邊信息
LL value[32 * maxn];                //節點存儲的值
int node_cnt;                       //樹中當前節點個數

inline void init(){                 //樹清空
    node_cnt = 1;
    memset(ch[0],0,sizeof(ch));
}           

inline void Insert(LL x){           //在字典樹中插入 X    
                                    //和一般字典樹的操作相同 將X的二進制插入到字典樹中
    int cur = 0;
    for(int i = 32;i >= 0;--i){
        int idx = (x >> i) & 1;
        if(!ch[cur][idx]){
            memset(ch[node_cnt],0,sizeof(ch[node_cnt]));
            ch[cur][idx] = node_cnt;
            value[node_cnt++] = 0;
        }
            cur = ch[cur][idx];
        }
        value[cur] = x;             //最後的節點插入value
}

inline LL Query(LL x){              //在字典樹中查找和X異或的最大值的元素Y 返回Y的值
    int cur = 0;
    for(int i = 32;i >= 0;--i){
        int idx = (x >> i) & 1;
        if(ch[cur][idx ^ 1]) cur = ch[cur][idx ^ 1];
        else cur = ch[cur][idx];
    }
    return value[cur];
}

KMP

const int maxn = 100;
char s[maxn],p[maxn];
int fail[maxn];
/*  p爲模式串
**  f爲保存失配邊的數組
**
*/
void getFail(char* p,int* f){
    int m = strlen(p);
    f[0] = 0; f[1] = 0;
    for(int i = 1;i < m;++i){
        int j = f[i];
        while(j && p[i] != p[j]) j = f[j];
        f[i + 1] = p[i] == p[j] ? j + 1 : 0;
    }
}
/*
**  s爲文本串 p爲模式串,fail保存失配邊
**  匹配成功返回true
**  失敗返回false
*/
bool Match(char* s,char* p,int* fail){
    getFail(p,fail);//得到fail數值
    int m = strlen(p),n = strlen(s);
    int i = 0, j = 0;
    while(i < n){
        while(i < n && j < m && s[i] == s[j]){//新一輪匹配
            i++,j++;
        }
        if(j == m) return true;//匹配成功
        j--;
        while(j && p[j] != s[i]) j = fail[j];//根據fail跳轉
    }
    return false;
}

AC自動機

const int maxn = 10000 * 50 + 50,sigma_size = 26;

/** AC_AUTOMATON */
int ch[maxn][sigma_size],fail[maxn],tot;
int value[maxn];

/** 初始化 */
void Init(){
    memset(ch[0],0,sizeof ch[0]);
    tot = 1;
    fail[0] = -1;value[0] = 0;
}

/** 插入字符串 s */
void Insert(char* s){
    int idx,cur = 0;
    while( *s ){
        idx = *s - 'a';
        if(ch[cur][idx] == 0){
            memset(ch[tot],0,sizeof ch[tot]);
            fail[tot] = 0;
            value[tot] = 0;
            ch[cur][idx] = tot++;
        }
        cur = ch[cur][idx];
        s++;
    }
    value[cur]++;
}

/** GetFail */
void GetFail(){
    queue<int> Q;
    Q.push(0);
    fail[0] = -1;
    int cur,idx,f;
    while(!Q.empty()){
        cur = Q.front();Q.pop();
        for(int i = 0;i < sigma_size;++i){
            if(ch[cur][i]){
                f = fail[cur];
                while(f != -1 && ch[f][i] == 0) f = fail[f];
                fail[ch[cur][i]] = (f == -1) ? 0 : ch[f][i];
                Q.push(ch[cur][i]);
            }
            else{
                f = fail[cur];
                ch[cur][i] = (f == -1) ? 0 : ch[f][i];
            }
        }
    }
}
/**  以上具有通用性 */
/** 匹配 */
int Search(char *s){
    int cur = 0,idx,ret = 0,tmp;
    while(*s){
        idx = *s - 'a';
        tmp = cur = ch[cur][idx];
        if(value[tmp]) while(tmp){
            ret += value[tmp];value[tmp] = 0;
            tmp = fail[tmp];
        }
        s++;
    }
    return ret;
}

MANACHER

const int maxn = 500;
int dis[maxn];
char str1[maxn],str2[maxn];

int get_dis(){
    int len = strlen(str1);
    str2[0] = '$';
    char* str_a = str2 + 1;
    for(int i = 0;i <= len;++i){
        str_a[i * 2] = '#';
        str_a[i * 2 + 1] = str1[i];
    }
    int id = 0, mx = 1,len2 = strlen(str2);
    for(int i = 1;i < len2;++i){
        if(mx > i){
            dis[i] = (dis[id * 2 - i] < (mx - i) ? dis[2 * id - i] : (mx - i));
        }
        else dis[i] = 1;
        while(str2[i - dis[i]] == str2[i + dis[i]]) dis[i]++;
        if(i + dis[i] > mx){
        mx = i + dis[i];
            id = i;
        }
    }
    return len2;
}

後綴數組

int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(int *r,int *sa,int n,int m)
{
    int i,j,p,*x=wa,*y=wb,*t;

    for(i=0;i<m;i++) ws[i]=0;
    for(i=0;i<n;i++) ws[x[i]=r[i]]++;
    for(i=1;i<m;i++) ws[i]+=ws[i-1];
    for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
    for(j=1,p=1;p<n;j*=2,m=p)
    {

        for(p=0,i=n-j;i<n;i++) y[p++]=i;
        for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;

        for(i=0;i<n;i++) wv[i]=x[y[i]];

        for(i=0;i<m;i++) ws[i]=0;
        for(i=0;i<n;i++) ws[wv[i]]++;
        for(i=1;i<m;i++) ws[i]+=ws[i-1];
        for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
        x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
    return;
}
int rank[maxn],height[maxn];
void calheight(int *r,int *sa,int n)
{
    int i,j,k=0;
    for(i=1;i<=n;i++) rank[sa[i]]=i;
    for(i=0;i<n;height[rank[i++]]=k)
    for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
    return;
}

迴文樹

const int MAXN = 100005;

struct node {
    int next[26];   //邊
    int len;        //迴文串長度
    int sufflink;   //後綴指針
    int num;
};

int len;
char s[MAXN];
node tree[MAXN];
int num;            // node 1 - root with len -1, node 2 - root with len 0
int suff;           // max suffix palindrome
long long ans;

bool addLetter(int pos) {

    int cur = suff, curlen = 0;
    int let = s[pos] - 'a';

    while (true) {
        curlen = tree[cur].len;                                     //當前可能上一個迴文串長度
        if (pos - 1 - curlen >= 0 && s[pos - 1 - curlen] == s[pos]) //如果能形成行如XAX的迴文串
            break;
        cur = tree[cur].sufflink;                                   //查找失敗 找到更小的迴文
    }
    if (tree[cur].next[let]) {                                      //這個節點已經存在
        suff = tree[cur].next[let];                                 //更新最長前綴值
        return false;
    }

    num++;
    suff = num;
    tree[num].len = tree[cur].len + 2;
    tree[cur].next[let] = num;              //加一個節點

    if (tree[num].len == 1) {               //只有一個X
        tree[num].sufflink = 2;             //指向空串
        tree[num].num = 1;
        return true;
    }

    while (true) {
        cur = tree[cur].sufflink;
        curlen = tree[cur].len;
        if (pos - 1 - curlen >= 0 && s[pos - 1 - curlen] == s[pos]) {
            tree[num].sufflink = tree[cur].next[let];
            break;
        }
    }
    tree[num].num = 1 + tree[tree[num].sufflink].num;
    return true;
}

void initTree() {
    num = 2; suff = 2;
    tree[1].len = -1; tree[1].sufflink = 1;
    tree[2].len = 0; tree[2].sufflink = 1;
}

字典樹

struct Trie{
    /**
    *   maxnode:    Trie樹中最多可能的節點個數 上限爲字符串個數 * 最長長度
    *   sigma_size: 組成字符串的字符種類
    *   ch:         邊
    *   value:      節點的值
    *   sz:         Trie樹的總節點個數
    */
    int ch[maxnode][sigma_size];
    int value[maxnode];
    int sz;
    int IDX(char c) {return c - 'a';}
    Trie(){
        sz = 1;
        memset(ch[0],0,sizeof(ch[0]));
    }

    /**
    *  字符串s插入Trie中 值爲V
    */
    void Insert(char* s,int v){
        int u = 0,len = strlen(s);
        for(int i = 0;i < len;++i){
            int c = IDX(s[i]);
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof(ch[sz]));
                value[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        value[u] = v;
    }

    /**
    *   查找字符串s 返回v
    */
    int Search(char* s){
        int cur = 0,idx;
        while(*s){
            idx = IDX(*s);
            if(ch[cur][idx] == 0) return -1;
            cur = ch[cur][idx];
            s++;
        }
        return value[cur];
    }
};

線段樹

#include <bits/stdc++.h>
using namespace std;

/** 線段樹模板 */
/** 以求區間和爲例 */
#define lson rt << 1 , l ,mid
#define rson rt << 1 | 1,mid + 1,r
const int maxn = 50000 + 50;
int v[maxn << 2],laze[maxn << 2];
int A[maxn];

// 向下Push laze標記
void PushDown(int rt,int l,int r){
    if(laze[rt]){
        int mid = l + r >> 1,lcnt = mid - l + 1,rcnt = r - mid;
        v[rt << 1] = v[rt << 1] + lcnt * laze[rt];
        v[rt << 1 | 1] = v[rt << 1 | 1] + rcnt * laze[rt];
        laze[rt << 1] += laze[rt];laze[rt << 1 | 1] += laze[rt];
        laze[rt] = 0;
    }
}
//向上更新sum值
void PushUp(int rt){
    v[rt] = v[rt << 1] + v[rt << 1 | 1];
}
void Build(int rt,int l,int r){
    if(l == r){
        v[rt] = A[l];return;
    }
    int mid = l + r >> 1;
    Build(lson),Build(rson);
    laze[rt] = 0;
    PushUp(rt);
}

//將區間L,R 增加X
void Update(int rt,int l,int r,int L,int R,int x){
    if(L <= l && R >= r){
        v[rt] += x * (r - l + 1);
        laze[rt] += x;
        return;
    }
    PushDown(rt,l,r);
    int mid = l + r >> 1;
    if(L <= mid) Update(lson,L,R,x);
    if(R > mid) Update(rson,L,R,x);
    PushUp(rt);
}

int Query(int rt,int l,int r,int L,int R){
    if(L <= l && R >= r){
        return v[rt];
    }
    PushDown(rt,l,r);
    int mid = l + r >> 1;
    int ret = 0;
    if(L <= mid) ret += Query(lson,L,R);
    if(R > mid) ret += Query(rson,L,R);
    PushUp(rt);
    return ret;
}

左偏堆

int key[maxn],dis[maxn],ch[maxn][2];
/**合併以a,b爲堆頂的堆*/
int Merge(int a,int b){
    if(!a) return b;if(!b) return a;
    if(key[a] < key[b]) swap(a,b);
    ch[a][1] = Merge(ch[a][1],b);
    if(dis[ch[a][0]] < dis[ch[a][1]]) swap( ch[a][0],ch[a][1] );
    if(ch[a][1] == 0) dis[a] = 0;
    else dis[a] = dis[ch[a][1]] + 1;
    return a;
}

大整數

struct BigInteger{
    int A[25];
    enum{MOD = 10000};
    BigInteger(){memset(A, 0, sizeof(A)); A[0]=1;}
    void set(int x){memset(A, 0, sizeof(A)); A[0]=1; A[1]=x;}
    void print(){
        printf("%d", A[A[0]]);
        for (int i=A[0]-1; i>0; i--){
            if (A[i]==0){printf("0000"); continue;}
            for (int k=10; k*A[i]<MOD; k*=10) printf("0");
            printf("%d", A[i]);
        }
        printf("\n");
    }
    int& operator [] (int p) {return A[p];}
    const int& operator [] (int p) const {return A[p];}
    BigInteger operator + (const BigInteger& B){
        BigInteger C;
        C[0]=max(A[0], B[0]);
        for (int i=1; i<=C[0]; i++)
            C[i]+=A[i]+B[i], C[i+1]+=C[i]/MOD, C[i]%=MOD;
        if (C[C[0]+1] > 0) C[0]++;
        return C;
    }
    BigInteger operator * (const BigInteger& B){
        BigInteger C;
        C[0]=A[0]+B[0];
        for (int i=1; i<=A[0]; i++)
            for (int j=1; j<=B[0]; j++){
                C[i+j-1]+=A[i]*B[j], C[i+j]+=C[i+j-1]/MOD, C[i+j-1]%=MOD;
            }
        if (C[C[0]] == 0) C[0]--;
        return C;
    }
};

快速輸入 (整數)

inline bool scan_d(int &num)  
{
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        }
        if(IsN) num=-num;
        return true;
}

快速輸入 (實數)

inline bool scan_lf(double &num)  
{
        char in;double Dec=0.1;
        bool IsN=false,IsD=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&in!='.'&&(in<'0'||in>'9'))
                in=getchar();
        if(in=='-'){IsN=true;num=0;}
        else if(in=='.'){IsD=true;num=0;}
        else num=in-'0';
        if(!IsD){
                while(in=getchar(),in>='0'&&in<='9'){
                        num*=10;num+=in-'0';}
        }
        if(in!='.'){
                if(IsN) num=-num;
                return true;
        }else{
                while(in=getchar(),in>='0'&&in<='9'){
                        num+=Dec*(in-'0');Dec*=0.1;
                }
        }
        if(IsN) num=-num;
        return true;
}

掃描線 √

using namespace std;
const int maxn = 100 + 5;
const int TOT_SEG = maxn * 2;
/** Seg
**  l,r,h 分別爲線段的左端點,右端點,高
**  f 標識上下邊
*/
struct Seg{
    int f;
    double l,r,h;
    void set(double ll,double rr,double hh,int d){
        l = ll,r = rr,h = hh,f = d;
    }
}Segs[TOT_SEG];
bool cmp(const Seg& a,const Seg& b){
    return a.h < b.h;
}
double AR[TOT_SEG]; /** 區間長度 */
map<double,int> POS; /** 將端點 HASH 到區間上 */
int FALG[TOT_SEG]; /** 區間被覆蓋的次數 */
int Seg_CNT,HASH_SEG_CNT;
void SEG_HASH(){
    POS.clear();HASH_SEG_CNT = 2;
    sort(Segs + 1,Segs + Seg_CNT,cmp);
    sort(AR + 1,AR + Seg_CNT);
    for(int i = 2;i < Seg_CNT;++i){
        if(AR[i] != AR[i - 1]){
            AR[HASH_SEG_CNT] = AR[i];
            POS[AR[i]] = HASH_SEG_CNT++;
        }
    }
    for(int i = 1;i < HASH_SEG_CNT;++i){
        AR[i] = AR[i + 1] - AR[i];
    }
}

1~MOD的逆元 √

#define mod 9973ll
typedef long long LL;
LL inv[mod];
inv[1] = 1;
for(int i = 2;i < mod;++i) inv[i] = (mod - mod / i) * (inv[mod % i]) % mod;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章