首页 > 其他分享 >个人模板

个人模板

时间:2023-05-09 17:23:19浏览次数:42  
标签:return 个人 int void mid seg id 模板

数学

快速幂

ll qmi(ll a,ll b,ll mod)
{
    ll ans = 1 % mod;
    while(b)
    {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}

快速乘

ll a,b,p;
ll qmimul(ll a, ll b, ll p)
{
    ll ans=0;
    a %= p;
    for(; b; b >>= 1)
    {
        if(b & 1)
            ans += a, ans %= p;
        a += a, a %= p;
    }
    return ans;
}
void solve()
{
    cin>>a>>b>>p;    cout<<qmimul(a,b,p)<<endl;
}

数论分块

void solve()
{
    ll n, ans = 0;  cin>>n;
    for(ll l = 1; l <= n; l++)
    {
        ll d = n / l, r = n / d;
        // ans + ...
        l = r;
    }
    return;
}

枚举子集,超集

void solve()
{
    int n;  cin>>n;
    // 枚举子集
    for(int i = 1; i < (1 << n); i++)
        for(int j = i; j; j = (j - 1) & i)
        {

        }
    // 枚举超集
    for(int i = 0; i < (1 << n); i++)
        for(int j = i; ; j = (j + 1) | i)
        {

            if(j == (1 << n) - 1)
                break;
        }
}

矩阵乘法

const int mod = 1e9+7;
const int N = 200;
int n, m;  
long long a[N + 1][N + 1], f[N + 1];
void aa()
{
    long long w[N + 1][N + 1];
    memset(w, 0, sizeof w);
    for(int i = 1; i <= N; i++)
        for(int k = 1; k <= N; k++)
            if(a[i][k])
                for(int j = 1; j <= N; j++)
                    if(a[k][j])
                        w[i][j] += a[i][k] * a[k][j], w[i][j] %= mod;
    memcpy(a, w, sizeof a);
}

void fa()
{
    long long w[N + 1];
    memset(w, 0, sizeof w);
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= N; j++)
            w[i] += f[j] * a[j][i], w[i] %= mod;
    memcpy(f, w, sizeof f);
}

void matrixpow(int k)
{
    for(; k; k /= 2)
    {
        if(k & 1)
            fa();
        aa();
    }
}

void solve()
{
    cin>>n>>m;
    ll k;  cin>>k;
    // construct Martix
    matrixpow(k);
    cout<<f[ ]<<endl;
    return;
}

筛法 & 质数

线性筛

int tot, p[N], pr[N];
void prime(int n)
{
    for (int i = 2; i <= n; i++)
    {
        if (!p[i])    p[i] = i, pr[++tot] = i; 
        for (int j = 1; j <= tot && pr[j] * i <= n; j++) {
            p[pr[j] * i] = pr[j];
            if(p[i] == pr[j])   break;
        }
    }
}

埃式筛

int tot, p[N], pr[N];
void prime(int n)
{
    for(int i = 2; i <= n; i++)
    {
        if(p[i])    continue;
        pr[++tot] = i;  
        for(int j = i; j <= n / i; j++)     p[i * j] = 1;
    }
}

质因数分解

void primer(int x)
{
    for (int i = 2; i <= x / i; i++)
    {
        if (x % i == 0)
        {
            int s = 0;
            while (x % i == 0)
            {
                x = x / i;
                s++;
            }
            cout << i << " " << s << endl;
        }
    }
    if (x > 1)  cout << x << " " << 1 << endl;
    cout << endl;
}

欧拉函数

int n;
void solve()
{
    cin>>n;
    int ans = n;
    vector<int> p;
    for(int i = 2; i <= n / i; i++)
    {
        if(n % i == 0)
        {
            p.push_back(i);
            while(n % i == 0)   n /= i;
        }
    }
    if(n != 1)
        p.pb(n);
    for(auto pri : p)
        ans = ans / pri * (pri - 1);
    cout<<ans<<endl;
    return;
}

约数

最大公约数

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

求约数

vector<int> get_yueshu(int x)
{
    vector<int> a;
    for (int i = 1; i <= x / i; i++)
    {
        if (x % i == 0)
        {
            a.push_back(i);
            if (i != x / i) 
                a.push_back(x / i);
        }
    }
    sort(a.begin(), a.end());
    return a;
}

扩展欧几里得1

\(ax - by = \gcd(a, b)\) 的最小非负整数解 \((x,y)\)


int exgcd(int a, int b, int &x, int &y)
{
	if(b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	int xx, yy;
	int d = exgcd(b, a % b, xx, yy);
	x = yy;
	y = xx - (a / b) * yy;
	return d;
}

int main()
{
	int _;cin>>_;
	while(_--)
	{
		int a, b, x, y;
		cin>>a>>b;
		int d = exgcd(a, b, x, y);
		y = -y;
		while(x < 0 || y < 0)	x += b / d, y += a / d;
		while(x >= b / d && y >= a / d)	x -= b / d, y -= a / d;
		cout<<x<<" "<<y<<endl;
	}
}

扩展欧几里得2

\(ax + by = d\) 的 \(x\) 最小的解的非负整数解 \((x,y)\)

ll exgcd(ll a, ll b, ll &x, ll &y)
{
	if(b == 0)
	{
		x = 1; y = 0;
		return a;
	}
	ll xx,yy;
	ll d = exgcd(b, a % b, xx, yy);
	x = yy;
	y = xx - (a / b) * yy;
	return d;
}

int main()
{
	int _;cin>>_;
	while(_--)
	{
		ll a, b, x, y, m;
		scanf("%lld%lld%lld", &a, &b, &m);
		ll d = exgcd(a, b, x, y);
		if(m % d != 0)
		{
			puts("-1");
			continue;
		}
		a /= d;
		b /= d;
		m /= d;
		ll xx = (ll) x * (m % b) % b;
		if(xx < 0)	xx = xx + b;
		ll yy = (ll)(m - a * xx) / b;
		if(yy < 0)
			puts("-1");
		else
			printf("%lld %lld\n", xx, yy);
	}
}

逆元

线性

ll n, p, inv[N];
void solve()
{
    cin>>p>>n;
    inv[1] = 1;
    for(int i = 2; i <= n; i++)
        inv[i] = (p - p / i) * inv[p % i] % p;
    return;
}

快速幂求逆元

qmi(a, mod - 2, mod)

组合数

\(O(N^2)\)

int n,c[N][N];
void init()
{
    for(int i=0;i<=2000;i++)
        for(int j=0;j<=i;j++)
            if(j==0)    c[i][j]=1;
            else c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
void solve()
{
    int a,b;    cin>>a>>b;
    cout<<c[a][b]<<endl;
}

O(N)

int n;
ll f[N],infact[N];
void init()
{
    f[0] = infact[0] = 1;
    for(int i = 1; i <= 100000; i++)
    {
        f[i] = i * f[i - 1] % mod;
        infact[i] = infact[i - 1] * 1ll * qmi(i, mod-2, mod) % mod;
    }
}
void solve()
{
    int a,b;    cin>>a>>b;
    cout<<(f[a] * infact[b] % mod * infact[a - b] % mod)<<endl;
}

Lucas \(O(\log_pNp\log_p)\)

int C(int a, int b, int p)
{
    if (b > a) return 0;
    int res = 1;
    for (int i = 1, j = a; i <= b; i ++, j -- )
    {
        res = (ll)res * j % p;
        res = (ll)res * qmi(i, p - 2, p) % p;
    }
    return res;
}
int lucas(ll a, ll b, int p)
{
    if (a < p && b < p) return C(a, b, p);
    return (ll)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}

数据结构

单调栈

给定一个长度为 \(N\) 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 \(−1\)

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> x;
        while (tt && a[tt] >= x)    tt--;   //tt有,栈顶大于待入栈元素
        if (tt == 0) cout << "-1 ";         //第一个数,栈无
        else cout << a[tt] << " ";          //输出所求
        a[++tt] = x;                        //入栈,不符合的话下一次while就清理掉了
    }
    return 0;
}

单调队列

滑动窗口

int main()
{
    cin >> n>>k;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    int hh = 0, tt = -1;
    for (int i = 0; i < n; i++)
    {
        if (hh <= tt && i - k + 1 > qq[hh]) hh++;//处理框框队尾,框框满了处理队尾
        while (hh <= tt && a[qq[tt]] >= a[i])   tt--;   //队首
        qq[++tt] = i;                           //队列加入新下标       
        if (i >= k - 1) cout << a[qq[hh]]<<" "; //框框满了
    }
    cout << endl;
    hh = 0, tt = -1;
    for (int i = 0; i < n; i++)
    {
        if (hh <= tt && i - k + 1 > qq[hh]) hh++;
        while (hh <= tt && a[qq[tt]] <= a[i])   tt--;
        qq[++tt] = i;
        if (i >= k - 1) cout << a[qq[hh]]<<" ";
    }
    return 0;
}

并查集

普通板子

int find(int x)
{
    if (fa[x] != x)      fa[x] = find(fa[x]);
    return fa[x];
}

封装DSU

struct DSU {
    std::vector<int> p, siz;
    DSU(int n) : p(n + 1), siz(n + 1, 1) { std::iota(p.begin(), p.end(), 0); }
    int find(int x) {
        return p[x] == x ? x : p[x] = find(p[x]);
    }
    bool same(int x, int y) { return find(x) == find(y); }
    bool merge(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return false;
        siz[x] += siz[y];
        p[y] = x;
        return true;
    }
    int size(int x) { return siz[find(x)]; }
};

哈希

单哈希板子

const int p = 9999971, base = 101;
int n , m, c[N + 10], ha[N + 10], hb[N + 10];
char a[N + 10], b[N + 10];
int main()
{
    cin>>n>>m;
    cin>>a + 1>>b + 1;
    c[0] = 1;
    for(int i = 1; i <= 200000; i++)
        c[i] = (c[i - 1] * base) % p;
    for(int i = 1; i <= n; i++)
        ha[i] = (ha[i - 1] * base + a[i] - 'a') % p;
    for(int i = 1; i <= m; i++)
        hb[i] = (hb[i - 1] * base + b[i] - 'a') % p;
    int ans = 0;
    for(int i = 1; i + m - 1 <= n; i++)
        if((ha[i + m - 1] - 1ll * ha[i - 1] * c[m] % p + p) % p == hb[m])
            ++ans;
    cout<<ans<<endl;
    return 0;
}

双哈希封装

typedef pair<long long, long long> pll;
struct DoubleStringHash
{
    vector<long long> h1, h2, w1, w2;
    long long base1 = 131, base2 = 13331;
    long long p1 = 1e9 + 7, p2 = 1e9 + 9;
    void init(string s) {
        int len = s.size();
        s = " " + s;
        h1.resize(len + 1), w1.resize(len + 1);
        h2.resize(len + 1), w2.resize(len + 1);
        h1[0] = 0, w1[0] = 1;
        h2[0] = 0, w2[0] = 1;
        for(int i = 1; i <= len; i++) {
            h1[i] = (h1[i - 1] * base1 + s[i]) % p1, w1[i] = w1[i - 1] * base1 % p1;
            h2[i] = (h2[i - 1] * base2 + s[i]) % p2, w2[i] = w2[i - 1] * base2 % p2;
        }
    }
    pll get(int l, int r) {
        return {(h1[r] - h1[l - 1] * w1[r - l + 1] % p1 + p1) % p1, (h2[r] - h2[l - 1] * w2[r - l + 1] % p2 + p2) % p2};
    }
};

Trie tree

普通板子

bool isend[N];
int n, m, nxt[N][26], cnt;
void solve()
{
    cin>>n;
    for(int i = 1; i <= n; i++)
    {
        string s;   cin>>s;
        int len = s.size(), now = 0;
        for(int j = 0; j < len; j++)
        {
            int x = s[j] - 'a';
            if(!nxt[now][x])
                nxt[now][x] = ++cnt;
            now = nxt[now][x];
        }
        isend[now] = true;
    }
    cin>>m;
    for(int i = 1; i <= m; i++)
    {
        string s;   cin>>s;
        int len = s.size(), now = 0;
        bool ok = true;
        for(int j = 0; j < len; j++)
        {
            int x = s[j] - 'a';
            if(!nxt[now][x])
            {
                ok = false;   
                break;
            }
            now = nxt[now][x];
        }
        if(ok)
            if(!isend[now])
                ok = false;
        if(ok)
            cout<<1<<endl;
        else cout<<0<<endl;
    }
    return;
}

封装

struct trie 
{
    int nxt[500010][26], cnt;
    bool isend[500010];  // 该结点结尾的字符串是否存在

    void insert(string s) {  // 插入字符串
        int now = 0;
        int l = s.size();
        for (int i = 0; i < l; i++) 
        {
            int x = s[i] - 'a';
            if (!nxt[now][x]) nxt[now][x] = ++cnt;  // 如果没有,就添加结点
            now = nxt[now][x];
        }
        isend[now] = 1;
    }

    bool find(string s) {  // 查找字符串
        int now = 0;
        int l = s.size();
        for (int i = 0; i < l; i++) {
            int x = s[i] - 'a';
            if (!nxt[now][x]) return 0;
            now = nxt[now][x];
        }
        return isend[now];
    }
}tr;

void solve()
{
    int n;  cin>>n;
    for(int i = 1; i <= n; i++)
    {
        string s;   cin>>s;
        tr.insert(s);
    }
    cin>>n;
    for(int i = 1; i <= n; i++)
    {
        string s;   cin>>s;
        if(tr.find(s))
            cout<<1<<endl;
        else cout<<0<<endl;
    }
    return;
}

KMP

int nxt[N];
void solve()
{
    string a, b; cin>>a>>b;
    int n = a.size(), m = b.size();
    a = "?" + a, b = "?" + b;
    vector<int> ans;
    for(int i = 2, j = 0; i <= n; i++)
    {
        while(j && a[i] != a[j + 1])  j = nxt[j];
        if(a[i] == a[j + 1])    j++;
        nxt[i] = j;
    }
    for(int i = 1, j = 0; i <= m; i++)
    {
        while(j == n || (j && b[i] != a[j + 1]))  j = nxt[j];
        if(b[i] == a[j + 1])    j++;
        if(j == n)
            ans.pb(i - n + 1);
    }
}

树状数组

普通模板

int n,q;
ll tr[N], a[N];
void modify(int x, ll s)
{
	for(; x <= n; x += x & -x)
		tr[x] += s;
}

ll query(int x)
{
	ll res = 0;
	for(; x; x -= x & -x)
		res += c[x];
	return res;
}

dls封装

template<class T>
struct BIT {
	T c[N];
	int size;
	void resize(int s) { size = s;}
	T query(int x) { // 1 ... x
		assert(x <= size);
		T s = 0;
		for (; x; x -= x & (-x)) {
			s += c[x];
		}
		return s;
	}

	void modify(int x, T s) { // a[x] += s
		assert(x != 0);
		for (; x <= size; x += x & (-x)) {
			c[x] += s;
		}
	} 
};

BIT<ll> c1, c2;  

线段树

线段树框架

struct info
{
	// ...
};

struct tag
{
	// ...
};

info operator + (const info &a, const info &b)
{
    info t;
    // ...
    return t;
}

struct segtree
{
    struct info val;
    struct tag tag;
    int sz;		// ...
}seg[N * 4];


void update(int id)
{
    // ...
}

void settag(int id, int tag)
{
    // ...
    // 更新val,tag
}
void pushdown(int id)
{
    if(seg[id].tag != null)
    {
        settag(id * 2, seg[id].tag.tag);
        settag(id * 2 + 1, seg[id].tag.tag);
        seg[id].tag = null;
    }
}

void build(int id, int l, int r)
{
    seg[id].sz = r - l + 1;
    if(l == r)
    {
        
        return;
    }
    int mid = (l + r) >> 1;
    build(id * 2, l, mid);
    build(id * 2 + 1, mid + 1, r);
    update(id);
}
void change(int id, int l, int r, int pos, struct tag tag)
{
	if(l == r)
	{
		settag(id, tag);
		return;
	}
	pushdown(id);
	int mid = (l + r) >> 1;
	if(pos <= mid)
		change(id * 2, l, mid, pos, tag);
	else change(id * 2 + 1, mid + 1, r, pos ,tag);
	update(id);
}

void modify(int id, int l, int r, int ql, int qr, struct tag tag)
{
    if(l == ql && r == qr)
    {
        settag(id, tag);
        return;
    }
    pushdown(id);
    int mid = (l + r) >> 1;
    if(qr <= mid)
        modify(id * 2, l, mid, ql, qr, tag);
    else if(ql > mid)
        modify(id * 2 + 1, mid + 1, r, ql, qr, tag);
    else 
        modify(id * 2, l, mid, ql, mid, tag),
        modify(id * 2 + 1, mid +1 , r, mid + 1, qr, tag);
    update(id);
}

info query(int id, int l, int r, int ql, int qr)
{
    if(ql == l && qr == r)
    {
        return seg[id].val;
    }
    pushdown(id);
    int mid = (l + r) >> 1;
    if(qr <= mid)
        return query(id * 2, l, mid, ql, qr);
    else if(ql > mid)
        return query(id * 2 + 1, mid + 1, r, ql, qr);
    else return query(id * 2, l, mid, ql, mid) + query(id * 2 + 1, mid + 1, r, mid + 1, qr);
}

动态开点线段树

struct segtree
{
	int l, r;
	ll s, tag;
}seg[N * 30];
int n, m, tot = 1;

void update(int &id)
{
	seg[id].s = seg[seg[id].l].s + seg[seg[id].r].s;
}

void settag(int id, int sz, ll t)
{
	seg[id].s += t * sz;
	seg[id].tag += t;
}

void pushdown(int id, int l, int r)
{
	if(seg[id].tag == 0) return;
	if(seg[id].l == 0)	seg[id].l = ++tot;
	if(seg[id].r == 0)	seg[id].r = ++tot;


	int mid = (l + r) >> 1;
	if(seg[id].l != 0)
		settag(seg[id].l, mid - l + 1, seg[id].tag);
	if(seg[id].r != 0)
		settag(seg[id].r, r - mid, seg[id].tag);
	seg[id].tag = 0;
}

void change(int &id, int l, int r, int pos, int val)
{
	if(!id) 
		id = ++tot;
	if(l == r)
	{
		seg[id].s = val;
		return;
	}
	int mid = (l + r) >> 1;
	if(pos <= mid)
		change(seg[id].l, l, mid, pos, val);
	else
		change(seg[id].r, mid + 1, r, pos, val);
	update(id);
}

void modify(int &id, int l, int r, int ql, int qr, ll t)
{
	if(!id)
		id = ++tot;
	if(l == ql && r == qr)
	{
		settag(id, r - l + 1, t);
		return;
	}
	pushdown(id, l ,r);
	int mid = (l + r) >> 1;
	if(qr <= mid)
		modify(seg[id].l, l, mid, ql, qr, t);
	else if(ql > mid)	
		modify(seg[id].r, mid + 1, r, ql, qr, t);
	else
	{
		modify(seg[id].l, l, mid, ql, mid, t);
		modify(seg[id].r, mid + 1, r, mid + 1, qr, t);
	}
	update(id);
}

ll query(int id, int l, int r, int ql, int qr)
{
	if(!id)
		id = ++tot;
	if(l == ql && r == qr)
	{
		return seg[id].s;
	}
	pushdown(id, l, r);
	int mid = (l + r) >> 1;
	if(qr <= mid)
		return query(seg[id].l, l, mid, ql, qr);
	else if(ql > mid)	
		return query(seg[id].r, mid + 1, r, ql, qr);
	else
		return query(seg[id].l, l, mid, ql, mid) +
			   query(seg[id].r , mid + 1, r, mid + 1, qr);
}

可持久化线段树第\(k\)小数

struct segtree
{
	int l, r, s;
}seg[N * 30];

vector<int> vx; 
int n, q, a[N], rt[N], tot;

void update(int id)
{
	seg[id].s = seg[seg[id].l].s + seg[seg[id].r].s;
}

int build(int l, int r)
{
	int id = ++tot;
	if(l == r)
		return id;
	int mid = (l + r) >> 1;
	seg[id].l = build(l, mid);
	seg[id].r = build(mid + 1, r);
	return id; 
}

int change(int u, int l, int r, int pos)
{
	int id = ++tot;
	seg[id] = seg[u];
	if(l == r)	
	{
		seg[id].s++;
		return id;
	}
	int mid = (l + r) >> 1;
	if(pos <= mid)
		seg[id].l = change(seg[u].l, l, mid, pos);
	else
		seg[id].r = change(seg[u].r, mid + 1, r, pos);
	update(id);
	return id;
}

int query(int v, int u, int l, int r, int x)
{
	if(l == r)
		return l;
	int cnt = seg[seg[u].l].s - seg[seg[v].l].s;
	int mid = (l + r) >> 1;
	if(x <= cnt)
		return query(seg[v].l, seg[u].l, l, mid, x);
	else
		return query(seg[v].r, seg[u].r, mid + 1, r, x - cnt);		
}

void solve()
{   
	cin>>n>>q;
	for(int i = 1; i <= n; i++)
	{
		cin>>a[i];
		vx.push_back(a[i]);
	}
	sort(vx.begin(), vx.end());
	vx.erase(unique(vx.begin(), vx.end()), vx.end());
	rt[0] = build(1, vx.size());
	for(int i = 1; i <= n; i++)
		rt[i] = change(rt[i - 1], 1, vx.size(), lower_bound(vx.begin(), vx.end(), a[i]) - vx.begin() + 1);
	
	while(q--)
	{
		int l, r, k;	cin>>l>>r>>k;
		cout<<vx[query(rt[l - 1], rt[r], 1, vx.size(), k) - 1]<<endl;
	}		
}

可持久化线段树前\(k\)大之和

int n, m, q, tot, rt[N], a[N];
ll mi[N];
vector<int> vx;

struct segtree
{
	int l, r, cnt;
	ll s, val; 
}seg[N * 30];

void update(int id)
{
	seg[id].s = seg[seg[id].l].s + seg[seg[id].r].s;
	seg[id].cnt = seg[seg[id].l].cnt + seg[seg[id].r].cnt;
}

int build(int l, int r)
{
	int id = ++tot;
	if(l == r)
	{
		return id;
	}
	int mid = (l + r) >> 1;
	seg[id].l = build(l, mid);
	seg[id].r = build(mid + 1, r);
	update(id);
	return id;
}

int change(int u, int l, int r, int pos)
{
	int id = ++tot;
	seg[id] = seg[u];
	if(l == r)
	{
		seg[id].s = seg[id].s + vx[pos - 1];
		seg[id].cnt = seg[id].cnt + 1;
		seg[id].val = vx[l - 1];
		return id;
	}
	int mid = (l + r) >> 1;
	if(pos <= mid)
		seg[id].l = change(seg[id].l, l, mid, pos);
	else
		seg[id].r = change(seg[id].r, mid + 1, r, pos);
	update(id);
	return id;
}

ll query(int v, int u, int l, int r, int k)
{
	if(l == r)
	{
		return seg[u].val * k;
	}
	int mid = (l + r) >> 1;
	int tmp = seg[seg[u].r].cnt - seg[seg[v].r].cnt;
	if(tmp >= k)
		return query(seg[v].r, seg[u].r, mid + 1, r, k);
	else
		return seg[seg[u].r].s - seg[seg[v].r].s
		+ query(seg[v].l, seg[u].l, l, mid, k - tmp);
}

void  solve()
{
	tot = 0;
	vx.clear();
	
	cin>>n;
	for(int i = 1; i <= n; i++)
	{
		cin>>a[i];
		vx.push_back(a[i]);
	}
	
	sort(vx.begin(), vx.end());
	vx.erase(unique(vx.begin(), vx.end()), vx.end());	
	int m = vx.size();
	
	rt[0] = build(1, m);
	for(int i = 1; i <= n; i++)
	{
		int pos = lower_bound(vx.begin(), vx.end(), a[i]) - vx.begin() + 1;
		rt[i] = change(rt[i - 1], 1, m, pos);
	}

	cin>>q;
	for(int i = 1; i <= q; i++)
	{
		int l, r, k;	cin>>l>>r>>k;
		int mm = r - l + 1;
		int x = l, y = l + mm - 1;
		ll ans = query(rt[x - 1], rt[y], 1, m, k) + mi[mm];
		cout<<ans<<'\n'; 
	}
}

树链剖分 点权

//  AC one more times
ll mod, w[N];
vector<int> e[N];
int n, root, q;
int tot, l[N], r[N], tid[N], top[N], bs[N], sz[N], f[N], dep[N];

void dfs1(int u, int fa)
{
    sz[u] = 1;
    dep[u] = dep[fa] + 1;
    bs[u] = -1;
    f[u] = fa;
    for(auto v : e[u])
    {
        if(v == fa) continue;
        dfs1(v, u);
        sz[u] +=sz[v];
        if(bs[u] == -1 || sz[v] > sz[bs[u]])
            bs[u] = v;
    }

}

void dfs2(int u,int t)
{
    l[u] = ++tot;
    tid[tot] = u;
    top[u] = t;
    if(bs[u] != -1)
        dfs2(bs[u], t);
    for(auto v : e[u])
    {
        if(v == bs[u] || v == f[u])    continue;
        dfs2(v, v);
    }
    r[u] = tot;
}

struct segtree
{
    ll s, tag, sz;
}seg[N * 4];

void update(int id)
{
    seg[id].s = seg[id * 2].s + seg[id * 2 + 1].s;
    seg[id].s %= mod;
    seg[id].sz = seg[id * 2].sz + seg[id * 2 + 1].sz;
}

void settag(int id, ll tag)
{
    seg[id].tag += tag;
    seg[id].s += tag * seg[id].sz, seg[id].s %= mod;
}

void pushdown(int id)
{
    if(seg[id].tag != 0)
    {
        settag(id * 2, seg[id].tag);
        settag(id * 2 + 1, seg[id].tag);
        seg[id].tag = 0;
    }
}

void build(int id, int l, int r)
{
    seg[id].sz = r - l + 1;
    if(l == r)
    {
        seg[id].s = w[tid[l]];
        return;
    }
    int mid = (l + r) >> 1;
    build(id * 2, l, mid);
    build(id * 2 + 1, mid + 1, r);
    update(id);
}

void modify(int id, int l, int r, int ql, int qr, ll tag)
{
	if(l > r)	return;
    if(l == ql && r == qr)
    {
        settag(id, tag);
        return;
    }
    pushdown(id);
    int mid = (l + r) >> 1;
    if(qr <= mid)
        modify(id * 2, l, mid, ql, qr, tag);
    else if(ql > mid)
        modify(id * 2 + 1, mid + 1, r, ql, qr, tag);
    else 
    {
        modify(id * 2, l, mid, ql, mid, tag);
        modify(id * 2 + 1, mid + 1, r, mid + 1, qr, tag);
    }
    update(id);
}

ll query(int id, int l, int r, int ql, int qr)
{
	if(l > r)	return 0;
    if(l == ql && r == qr)
    {
        return seg[id].s;
    }
    pushdown(id);
    int mid = (l + r) >> 1;
    if(qr <= mid)
        return query(id * 2, l, mid, ql, qr);
    else if(ql > mid)
        return query(id * 2 + 1, mid + 1, r, ql, qr);
    else 
    {
        return (query(id * 2, l, mid, ql, mid) +
        query(id * 2 + 1, mid + 1, r, mid + 1, qr)) % mod;
    }
    update(id);

}

void modify(int u, int v, ll k)
{
    while(top[u] != top[v])
    {
        if(dep[top[u]] > dep[top[v]])
        {
            modify(1, 1, n, l[top[u]], l[u], k);
            u = f[top[u]];
        }
        else
        {
            modify(1, 1, n, l[top[v]], l[v], k);
            v = f[top[v]];
        }
    }
    if(dep[u] < dep[v]) swap(u, v);
    modify(1, 1, n, l[v], l[u], k);
}

ll query(int u, int v)
{
    ll ans = 0;
    while(top[u] != top[v])
    {
        if(dep[top[u]] > dep[top[v]])
        {
            ans += query(1, 1, n, l[top[u]], l[u]);
            ans %= mod;
            u = f[top[u]];
        }
        else
        {
            ans += query(1, 1, n, l[top[v]], l[v]);
            ans %= mod;
            v = f[top[v]];
        }
    }
    if(dep[u] < dep[v]) swap(u, v);
    ans += query(1, 1, n, l[v], l[u]);
    ans %= mod;
    return ans;
}

void solve()
{
    cin>>n>>q>>root>>mod;
    for(int i = 1; i <= n; i++)
        cin>>w[i];
    for(int i = 1; i < n; i++)
    {
        int u, v;    cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs1(root, 0);
    dfs2(root, root);
    build(1, 1, n);
    while(q--)
    {
        int op; cin>>op;
        if(op == 1)
        {
            int u, v;   cin>>u>>v;
            ll k;   cin>>k;
            modify(u, v, k);
        }
        else if(op == 2)
        {
            int u, v;   cin>>u>>v;
            cout<<query(u, v) % mod<<endl;
        }
        else if(op == 3)
        {
            int u;  ll k;
            cin>>u>>k;
            modify(1, 1, n, l[u], r[u], k);
        }
        else if(op == 4)
        {
            int u;  cin>>u;
            cout<<query(1, 1, n, l[u], r[u]) % mod<<endl;
        }
    }
    return;
}

树链剖分 边权下放

vector<PII> e[N];
int n, q;
int tot, l[N], r[N], tid[N], top[N], bs[N], sz[N], f[N], dep[N];
ll w[N];
pii edge[N];
void dfs1(int u, int fa)
{
    sz[u] = 1;
    dep[u] = dep[fa] + 1;
    bs[u] = -1;
    f[u] = fa;
    for(auto v : e[u])
    {
        if(v.fi == fa) continue;
        dfs1(v.fi, u);
        w[v.fi] = v.se;
        sz[u] +=sz[v.fi];
        if(bs[u] == -1 || sz[v.fi] > sz[bs[u]])
            bs[u] = v.fi;
    }

}

void dfs2(int u,int t)
{
    l[u] = ++tot;
    tid[tot] = u;
    top[u] = t;
    if(bs[u] != -1)
        dfs2(bs[u], t);
    for(auto v : e[u])
    {
        if(v.fi == bs[u] || v.fi == f[u])    continue;
        dfs2(v.fi, v.fi);
    }
    r[u] = tot;
}

struct info 
{
    ll s, mav, miv;
};

info operator + (const info &a, const info &b)
{
    return (info){a.s + b.s, max(a.mav, b.mav), min(a.miv, b.miv)};
}

struct segtree
{
    struct info val;
    int tag;
}seg[N * 4];

void update(int id)
{
    seg[id].val = seg[id * 2].val + seg[id * 2 + 1].val;
}

void settag(int id, int tag)
{
    seg[id].tag += tag, seg[id].tag %= 2;
    swap(seg[id].val.mav, seg[id].val.miv);
    seg[id].val = {-seg[id].val.s, -seg[id].val.mav, -seg[id].val.miv};
}

void pushdown(int id)
{
    if(seg[id].tag == 1)
    {
        settag(id * 2, seg[id].tag);
        settag(id * 2 + 1, seg[id].tag);
        seg[id].tag = 0;
    }
}

void build(int id, int l, int r)
{
    seg[id].tag = 0;
    if(l == r)
    {
        seg[id].val = {w[tid[l]], w[tid[l]], w[tid[l]]};
        return;
    }
    int mid = (l + r) >> 1;
    build(id * 2, l, mid);
    build(id * 2 + 1, mid + 1, r);
    update(id);
}

void change(int id, int l, int r, int pos, ll ew)
{
    if(l == r)
    {
        seg[id].val = {ew, ew, ew};
        return;
    }
    pushdown(id);
    int mid = (l + r) >> 1;
    if(pos <= mid)
        change(id * 2, l, mid, pos, ew);
    else if(pos > mid)
        change(id * 2 + 1, mid + 1, r, pos, ew);
    update(id);
}
void modify(int id, int l, int r, int ql, int qr, ll tag)
{
    if(ql > qr || l > r) return;
    if(l == ql && r == qr)
    {
        settag(id, tag);
        return;
    }
    pushdown(id);
    int mid = (l + r) >> 1;
    if(qr <= mid)
        modify(id * 2, l, mid, ql, qr, tag);
    else if(ql > mid)
        modify(id * 2 + 1, mid + 1, r, ql, qr, tag);
    else 
    {
        modify(id * 2, l, mid, ql, mid, tag);
        modify(id * 2 + 1, mid + 1, r, mid + 1, qr, tag);
    }
    update(id);
}

info query(int id, int l, int r, int ql, int qr)
{
    if((ql > qr || l > r)) return (info){0, -100000000, 100000000};
    if(l == ql && r == qr)
    {
        return seg[id].val;
    }
    pushdown(id);
    int mid = (l + r) >> 1;
    if(qr <= mid)
        return query(id * 2, l, mid, ql, qr);
    else if(ql > mid)
        return query(id * 2 + 1, mid + 1, r, ql, qr);
    else 
    {
        return query(id * 2, l, mid, ql, mid) +
        query(id * 2 + 1, mid + 1, r, mid + 1, qr);
    }
    update(id);

}

void modify(int u, int v, ll k)
{
    while(top[u] != top[v])
    {
        if(dep[top[u]] > dep[top[v]])
        {
            modify(1, 1, n, l[top[u]], l[u], k);
            u = f[top[u]];
        }
        else
        {
            modify(1, 1, n, l[top[v]], l[v], k);
            v = f[top[v]];
        }
    }
    if(dep[u] < dep[v]) swap(u, v);
    modify(1, 1, n, l[v] + 1, l[u], k);
}

info query(int u, int v)
{
    info ans = (info){0, -100000000, 100000000};
    while(top[u] != top[v])
    {
        if(dep[top[u]] > dep[top[v]])
        {
            ans = ans + query(1, 1, n, l[top[u]], l[u]);
            u = f[top[u]];
        }
        else
        {
            ans = ans + query(1, 1, n, l[top[v]], l[v]);
            v = f[top[v]];
        }
    }
    if(dep[u] < dep[v]) swap(u, v);
    ans = ans + query(1, 1, n, l[v] + 1, l[u]);
    return ans;
}

void solve()
{
    cin>>n;
    for(int i = 1; i < n; i++)
    {
        int u, v, w;    cin>>u>>v>>w;
        u++, v++;
        edge[i] = {u, v};
        e[u].push_bcak({v, w});
        e[v].push_bcak({u, w});
    }
    dfs1(1, 0);
    dfs2(1, 1);
    build(1, 1, n);
    cin>>q;
    while(q--)
    {
        string op;  cin>>op;
        if(op == "C")
        {
            int i, w;   cin>>i>>w;
            int u = edge[i].fi, v = edge[i].se;
            if(dep[u] < dep[v]) swap(u, v);
            change(1, 1, n, l[u], w);
        }
        else if(op == "N")
        {
            int u, v;
            cin>>u>>v;
            u++, v++;
            modify(u, v, 1);
        }
        else if(op == "SUM")
        {
            int u, v;
            cin>>u>>v;
            u++, v++;
            cout<<query(u, v).s<<endl;            
        }
        else if(op == "MAX")
        {
            int u, v;
            cin>>u>>v;
            u++, v++;
            cout<<query(u, v).mav<<endl;            
        }
        else if(op == "MIN")
        {
            int u, v;
            cin>>u>>v;
            u++, v++;
            cout<<query(u, v).miv<<endl;            
        }
    }
}

ST表

const int LOGN = 21;
const int N = 100000;
int f[N + 10][LOGN + 2], LOG[N + 10];
int n, m;
void pre()
{
    LOG[1] = 0, LOG[2] = 1;
    for(int i = 3; i <= N; i++)
        LOG[i] = LOG[i / 2] + 1;
}
void solve()
{
    cin>>n>>m;
    for(int i = 1; i <= n; i++)   cin>>f[i][0];
    pre();
    for(int j = 1; j <= LOGN; j++)
    {
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
            f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
    }
    for(int i = 1; i <= m; i++)
    {
    	cin>>x>>y;
        int s = LOG[y - x + 1];
        cout<<max(f[x][s], f[y - (1 << s) + 1][s])<<endl;
    }
    return;
}

LCA

#include<bits/stdc++.h>
using namespace std;
const int N = 5000010;
const int LOGN = 20;

int n, m, root, dep[N], fa[N][LOGN + 2];
vector<int> e[N];

void dfs(int u, int from)
{
    dep[u] += dep[from] + 1;
    for(auto v : e[u]) {
        if(v == from) continue;
        fa[v][0] = u;
        dfs(v, u);
    }
}

void lca_init()
{
    for(int j = 1; j <= LOGN; j++)
        for(int i = 1; i <= n; i++)
            fa[i][j] = fa[fa[i][j - 1]][j - 1];
}
int lca_query(int u, int v)
{
    if(dep[u] < dep[v])   swap(u, v);
    int d = dep[u] - dep[v];
    for(int j = LOGN; j >= 0; j--)
        if(d & (1 << j))
            u = fa[u][j];
    if(u == v)    return u;
    for(int j = LOGN; j >= 0; j--)
        if(fa[u][j] != fa[v][j])
            u = fa[u][j],v = fa[v][j];
    return fa[u][0];
}
int main()
{
    cin>>n>>m>>root;
    for(int i = 2; i <= n; i++)
    {
        int u, v;    cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs(root, 0);
    lca_init();
    while(m--)
    {
        int u, v;    cin>>u>>v;
        cout<<lca_query(u, v)<<endl;
    }
    return 0;
}

标签:return,个人,int,void,mid,seg,id,模板
From: https://www.cnblogs.com/magicat/p/17385691.html

相关文章

  • 1000个已成功入职的软件测试工程师简历经验总结:软件测试工程师简历项目经验怎么写?(含
    一、前言:浅谈面试 面试是我们进入一个公司的门槛,通过了面试才能进入公司,你的面试结果和你的薪资是息息相关的。那如何才能顺利的通过面试,得到公司的认可呢?面试软件测试要注意哪些问题呢?下面和笔者一起来看看吧。这里分享一下笔者十年测试生涯的面试总结!软件测试面试常......
  • 打卡 数据的最大值问题(重载+函数模板)
    两个类如下设计:类Time有三个数据成员,hh,mm,ss,分别代表时,分和秒,并有若干构造函数和一个重载-(减号)的成员函数。类Date有三个数据成员,year,month,day分别代表年月日,并有若干构造函数和一个重载>(<)(大于号或者小于号)的成员函数。要求设计一个函数模板template<classT>doublemaxn(Tx[]......
  • 模板类
    1、复数类Complex有两个数据成员:a和b,分别代表复数的实部和虚部,并有若干构造函数和一个重载-(减号,用于计算两个复数的距离)的成员函数。要求设计一个函数模板template<classT>doubledist(Ta,Tb)对int,float,Complex或者其他类型的数据,返回两个数据的间距。以上类名和函......
  • 模板层
    模板层一、模板简介在刚刚介绍完的视图层中我们提到,浏览器发送的请求信息会转发给视图进行处理,而视图在经过一系列处理后必须要有返回信息给浏览器。如果我们要返回html标签、css等数据给浏览器进行渲染,我们可以在视图中这么做fromdjango.shortcutsimportHttpResponseimpor......
  • 第十四届蓝桥杯省赛C++ B组(个人经历 + 题解)
    参赛感受这是我第一次参加蓝桥杯的省赛,虽然没什么参赛经验,但是自己做了很多前几届蓝桥杯的题,不得不说,这一届蓝桥杯省赛的难度相较于之前而言还是比较大的。之前很流行蓝桥杯就是暴力杯的说法,但是随着参赛人数的增多,比赛认可度的提升,比赛题目的质量也明显越来越高了。这次省赛涉及......
  • JAVA快速开发框架 一键生成表单模板代码
    从计算机诞生开始,虽然编程的形式随着硬件及软件的不断进步而不停迭代,但是从事计算机技术行业的人员始终与编写代码的任务紧密联系在一起。因此如何提高软件开发的效率和质量,一直是软件工程领域的重要问题之一。这一方面是由于在不同软件开发过程中存在大量相似代码复用的情况,多次......
  • JAVA快速开发框架 一键生成表单模板代码
    从计算机诞生开始,虽然编程的形式随着硬件及软件的不断进步而不停迭代,但是从事计算机技术行业的人员始终与编写代码的任务紧密联系在一起。因此如何提高软件开发的效率和质量,一直是软件工程领域的重要问题之一。这一方面是由于在不同软件开发过程中存在大量相似代码复用的情况,多次编......
  • GitHub搭建个人博客2023
    1.登录github2.上传一个index.html的文件3.点击settings-->然后点击pages3.选择分支->点击save ......
  • (hdu step 3.1.7)Children’s Queue(求n个人站在一起有m个人必须是连在一起的方案数)
    题目:Children’sQueueTimeLimit:2000/1000MS(Java/Others)MemoryLimit:65536/32768K(Java/Others)TotalSubmission(s):853AcceptedSubmission(s):479 ProblemDescriptionTherearemanystudentsinPHTSchool.Oneday,theheadmasterwhosen......
  • 2023ccpc湖北省赛/2023 Hubei Provincial Collegiate Programming Contest个人题解
    2023HubeiProvincialCollegiateProgrammingContestAPrimeMagicWalkAlonehasasequence\(a_1,a_2,...,a_n\),andhecanuseamagiconit:Chooseanoddprimenumber\(p\)andaninterval\([l,r]⊆[1,n]\)satisfying\(r−l+1=p\),andthenadd......