• 2022 纪中集训7.7


    T1

    image

    板子主席树

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 10;
    
    struct Node
    {
        int l,r;
        int cnt;
    }tr[N * 4 + N * 20];
    
    int n,m;
    int root[N],idx;
    vector<int> num;
    int a[N];
    
    void pushup(int u)
    {
        tr[u].cnt = tr[tr[u].l].cnt + tr[tr[u].r].cnt;
    }
    
    int find(int x)
    {
        return lower_bound(num.begin(),num.end(),x) - num.begin();
    }
    
    int build(int l,int r)
    {
        int p = ++ idx;
        if(l == r) return p;
        
        int mid = l + r >> 1;
        tr[p].l = build(l, mid) , tr[p].r = build(mid + 1,r);
        return p;
    }
    
    int insert(int p,int l,int r,int x)
    {
        int q = ++ idx;
        tr[q] = tr[p];
        
        if(l == r)
        {
            tr[q].cnt ++;
            return q;
        }
        
        int mid = l + r >> 1;
        if(x <= mid) tr[q].l = insert(tr[p].l,l,mid,x);
        else tr[q].r = insert(tr[p].r,mid+1,r,x);
        
        pushup(q);
        
        return q;
    }
    
    int L[N], R[N];
    int K, P;
    
    int query(int l,int r,int k)
    {
        if(l == r) return r;
        int cnt = 0;
    	for(int i=1;i<=K;i++) cnt += tr[tr[R[i]].l].cnt - tr[tr[L[i]].l].cnt;
        
        int mid = l + r >> 1;
        if(k <= cnt) 
    	{
    		for(int i=1;i<=K;i++) L[i] = tr[L[i]].l, R[i] = tr[R[i]].l;
    		return query(l,mid,k);
    	}
        else 
    	{
    		for(int i=1;i<=K;i++) L[i] = tr[L[i]].r, R[i] = tr[R[i]].r;
    		return query(mid+1,r,k-cnt);
    	}
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            num.push_back(a[i]);
        }
        
        sort(num.begin(),num.end());
        num.erase(unique(num.begin(),num.end()),num.end());
        
        root[0] = build(0,num.size()-1);
        
        for(int i=1;i<=n;i++) root[i] = insert(root[i-1],0,num.size()-1,find(a[i]));
        
        // while(m --)
        // {
        //     int l,r,k;
        //     scanf("%d%d%d",&l,&r,&k);
        //     printf("%d\n",num[query(root[r],root[l-1],0,num.size()-1,k)]);	
        // }
    
    	while(m --)
    	{
    		int x, y;
    		scanf("%d%d",&K,&P);
    		for(int i=1;i<=K;i++) 
    		{
    			scanf("%d%d",&x,&y);
    			L[i] = root[x-1], R[i] = root[y];
    		}
    		printf("%d\n", num[query(0,num.size()-1,P)]);
    	}
    
        return 0;
    }
    

    T2

    image
    树形DP

    \(f[u][0]\) u的子树中没有黑点的代价

    \(f[u][1]\) u的子树中没有白点的代价

    \(f[u][i]\) u的子树中只有一个白点的代价

    明显 \(f[u][2]\) 可以用 \(f[u][1]\) 减去最大的一条边得到。

    赛时由于用了 dfs,爆栈了。。。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    typedef pair<LL, LL> PII;
    const LL INF = 1e17;
    const LL N=300010, M = 2*N;
    
    LL n,root;
    LL col[N],in[N];
    LL f[N],g[N],h[N];
    
    struct Edge
    {
    	LL v,nxt;
    	LL w;
    }e[M];
    LL head[N], idx = 0;
    void add(LL u,LL v,LL w=0)
    {
    	e[++idx].v = v,e[idx].w = w, e[idx].nxt = head[u],head[u] = idx;
    }
    
    void bfs()
    {
    	queue<LL> q;
    
    	for (LL i=1;i<=n;i++) if (in[i]==1) q.push(i);
    
    	while (q.size())
    	{
    		LL u=q.front();
    		q.pop();
    		root=u;
    		in[u]=0;
    		
    		if (col[u]==0)
    		{
    			f[u]=INF;
    			for (LL i=head[u];i;i=e[i].nxt)
    			{
    				LL v=e[i].v;
    				if (!in[v]) g[u]+=min({f[v]+e[i].w,g[v],h[v]+e[i].w});
    			}
    			for (LL i=head[u];i;i=e[i].nxt)
    			{
    				LL v=e[i].v;
    				if (!in[v]) h[u]=min(h[u],h[v]+g[u]-min({f[v]+e[i].w,g[v],h[v]+e[i].w}));
    			}
    		}
    		
    		if (col[u]==1)
    		{
    			g[u]=INF;
    			for (LL i=head[u];i;i=e[i].nxt)
    			{
    				LL v=e[i].v;
    				if (!in[v])
    				{
    					f[u]+=min({f[v],g[v]+e[i].w,h[v]+e[i].w});
    					h[u]+=min({f[v]+e[i].w,g[v],h[v]+e[i].w});
    				}
    			}
    		}
    		
    		if (col[u]==2)
    		{
    			for (LL i=head[u];i;i=e[i].nxt)
    			{
    				LL v=e[i].v;
    				if (!in[v])
    				{
    					f[u]+=min({f[v],g[v]+e[i].w,h[v]+e[i].w});
    					g[u]+=min({f[v]+e[i].w,g[v],h[v]+e[i].w});
    				}
    			}
    			for (LL i=head[u];i;i=e[i].nxt)
    			{
    				LL v=e[i].v;
    				if (!in[v]) h[u]=min(h[u],h[v]+g[u]-min({f[v]+e[i].w,g[v],h[v]+e[i].w}));
    			}
    		}
    		
    		for (LL i=head[u];i;i=e[i].nxt)
    		{
    			LL v=e[i].v;
    			if (in[v]>1)
    			{
    				in[v]--;
    				if (in[v]==1) q.push(v);
    			}
    		}
    	}
    }
    
    int main()
    {
    	LL T;
    	scanf("%lld",&T);
    
    	while (T--)
    	{
    		memset(head,0,sizeof(head));
    		memset(in,0,sizeof(in));
    		idx=0;
    
    		scanf("%lld",&n);
    		for (LL i=1;i<=n;i++)
    		{
    			scanf("%lld",&col[i]);
    
    			if (col[i]==0) f[i]=INF,g[i]=0,h[i]=INF;
    			if (col[i]==1) f[i]=0,g[i]=INF,h[i]=0;
    			if (col[i]==2) f[i]=0,g[i]=0,h[i]=INF;
    		}
    		for (LL i=1;i<n;i++)
    		{
    			LL u,v,w;
    			scanf("%lld%lld%lld",&u,&v,&w);
    			add(u,v,w); add(v,u,w);
    			in[u]++; in[v]++;
    		}
    
    		bfs();
    		
    		printf("%lld\n",min({f[root],g[root],h[root]}));
    	}
    	return 0;
    }
    

    T3

    image
    先跑一次最短路。
    求出所以可能的最短路,并建图用作网络流。
    跑最大流求最小割。
    分别从起点和终点开始染色。
    枚举残留网络中的跨两个块的边,统计边权。
    若跨两个块的边权和不等于最小割的大小,则最小割不固定,方案不唯一。
    反之亦然。

    T4

    FHQ-treap 维护

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 2e5 + 10;
    typedef long long LL;
    
    struct FHQ
    {
    	int l, r;
    	int size, key;
    	LL val, sum, pre, suc, maxn;
    } fhq[N];
    int n, m;
    int rt = 0, cnt = 0;
    
    int newnode(int val)
    {
    	fhq[++cnt].size = 1;
    	fhq[cnt].sum = fhq[cnt].val = fhq[cnt].maxn = val;
    	fhq[cnt].pre = fhq[cnt].suc = max(0, val);
    	fhq[cnt].key = rand();
    	return cnt;
    }
    
    inline void pushup(int p)
    {
    	int l = fhq[p].l, r = fhq[p].r;
    	fhq[p].size = fhq[l].size + fhq[r].size + 1;
    	fhq[p].sum = fhq[l].sum + fhq[r].sum + fhq[p].val;
    	fhq[p].pre = max(fhq[l].pre, fhq[l].sum + fhq[p].val + fhq[r].pre);
    	fhq[p].suc = max(fhq[r].suc, fhq[l].suc + fhq[p].val + fhq[r].sum);
    	fhq[p].maxn = max(fhq[l].suc + fhq[p].val + fhq[r].pre, max(fhq[l].maxn, fhq[r].maxn));
    }
    
    inline int merge(int x, int y)
    {
    	if (!x || !y) return x | y;
    	if (fhq[x].key < fhq[y].key)
    	{
    		fhq[x].r = merge(fhq[x].r, y);
    		pushup(x);
    		return x;
    	}
    	else
    	{
    		fhq[y].l = merge(x, fhq[y].l);
    		pushup(y);
    		return y;
    	}
    }
    
    void split(int p, int sz, int &x, int &y)
    {
    	if (!p)
    		x = y = 0;
    	else
    	{
    		if (fhq[fhq[p].l].size < sz)
    		{
    			x = p;
    			split(fhq[p].r, sz - fhq[fhq[p].l].size - 1, fhq[p].r, y);
    		}
    		else
    		{
    			y = p;
    			split(fhq[p].l, sz, x, fhq[p].l);
    		}
    		pushup(p);
    	}
    }
    
    int main()
    {
    	srand(114514);
    	scanf("%d",&n);
    
    	fhq[0].maxn = -1e9;
    	for (int i = 1, x; i <= n; ++i)
    	{
    		scanf("%d",&x);
    		rt = merge(rt, newnode(x));
    	}
    
    	scanf("%d",&m);
    	char op[3];
    	int a, b, x, y, z;
    	while (m--)
    	{
    		scanf("%s%d", op, &a);
    		if (op[0] == 'I')
    		{
    			scanf("%d",&b);
    			split(rt, a - 1, x, y);
    			rt = merge(x, merge(newnode(b), y));
    		}
    		if (op[0] == 'D')
    		{
    			split(rt, a - 1, x, y);
    			split(y, 1, y, z);
    			rt = merge(x, z);
    		}
    		if (op[0] == 'R')
    		{
    			scanf("%d",&b);
    			split(rt, a - 1, x, y);
    			split(y, 1, y, z);
    			fhq[y].sum = fhq[y].val = fhq[y].maxn = b;
    			fhq[y].pre = fhq[y].suc = max(b, 0);
    			rt = merge(x, merge(y, z));
    		}
    		if(op[0] == 'Q')
    		{
    			scanf("%d",&b);
    			split(rt, b, y, z);
    			split(y, a - 1, x, y);
    			printf("%lld\n", fhq[y].maxn);
    			rt = merge(x, merge(y, z));
    		}
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    常用的STL
    CString,string,char数组的转换
    linux知识
    十一种通用滤波算法(转)
    修复被勒索病毒cl0p损坏的svn代码
    android shell 转发代理shell示例
    3proxy配置
    windbg调试写dmp,随机名字
    nexus6p刷机注意
    mysql语句学习
  • 原文地址:https://www.cnblogs.com/BorisDimitri/p/16455234.html
Copyright © 2020-2023  润新知