9月做题记录

Part 1.图论

 

1.分层图最短路

 

P6100 [USACO19FEB] Painting the Barn G

复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=205,K=1e5+5;
int n,m=200,k,h[M][M],res,ans,cntx[M][M],cnty[M][M],ansx[M][M],ansy[M][M],nx[2][M],ny[2][M],tmp;


int main() 
{
    cin>>n>>k;
    for(int i=1;i<=n;++i)
    {
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        ++x1,++y1,++x2,++y2;
        h[x1][y1]++,h[x2][y2]++;
        h[x1][y2]--,h[x2][y1]--;
    }
    for(int i=1;i<=m;++i)
    {
        for(int j=1;j<=m;++j)
        h[i][j]+=h[i-1][j]+h[i][j-1]-h[i-1][j-1],res+=(h[i][j]==k);
    }
    
    for(int i=1;i<=m;++i)
    {
        for(int j=1;j<=m;++j)
        {
            cntx[i][j]=cntx[i-1][j]+(h[i][j]==k-1)-(h[i][j]==k);
            cnty[i][j]=cnty[i][j-1]+(h[i][j]==k-1)-(h[i][j]==k);
        }
    }

    for(int i=1;i<=m;++i)
    {
        for(int j=1;j<=i;++j)
        {
            tmp=0;
            for(int c=1;c<=m;++c)
            {
                tmp=max(tmp+cntx[i][c]-cntx[j-1][c],0);
                ansx[i][j]=max(ansx[i][j],tmp);
            }
        }
    }
    for(int i=1;i<=m;++i)
    {
        for(int j=1;j<=i;++j)
        {
            tmp=0;
            for(int c=1;c<=m;++c)
            {
                tmp=max(tmp+cnty[c][i]-cnty[c][j-1],0);
                ansy[i][j]=max(ansy[i][j],tmp);
            }
        }
    }
    for(int i=1;i<=m;++i)
    {
        nx[0][i]=nx[0][i-1];
        for(int j=1;j<=i;++j)
        nx[0][i]=max(nx[0][i],ansx[i][j]);
    }
    for(int i=m;i>=1;--i)
    {
        nx[1][i]=nx[1][i+1];
        for(int j=m;j>=i;--j)
        nx[1][i]=max(nx[1][i],ansx[j][i]);
    }
    for(int i=1;i<=m;++i)
    {
        ny[0][i]=ny[0][i-1];
        for(int j=1;j<=i;++j)
        ny[0][i]=max(ny[0][i],ansy[i][j]);
    }
    for(int i=m;i>=1;--i)
    {
        ny[1][i]=ny[1][i+1];
        for(int j=m;j>=i;--j)
        ny[1][i]=max(ny[1][i],ansy[j][i]);
    }
    ans=res;
    for(int i=2;i<=m;++i) ans=max(ans,res+nx[0][i-1]+nx[1][i]);
    for(int i=2;i<=m;++i) ans=max(ans,res+ny[0][i-1]+ny[1][i]);
    printf("%d\n",ans);
    return 0;
}
复制代码

 

 

P3119 [USACO15JAN] Grass Cownoisseur G

主要是需要缩点,分层图最短路就比较板了。

复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=500005;
//要先缩点! 
int n,m,h[N],e[N],ne[N],idx =1,deg[N],f[N];
int dfn[N],low[N],tmp,q[N],indx,scc[N],tot,num[N],top;
void add(int a,int b){
    e[idx] = b;
    ne[idx] = h[a];
    h[a]=idx++;
}
void tarjan(int u)
{
    dfn[u]=low[u]=++tmp;
    q[++top] = u;
    for(int i=h[u],v;i;i=ne[i]){
        int j=e[i];
        if(!dfn[j]){
            tarjan(j);
            low[u]=min(low[u],low[j]);
        }else if(!scc[j]){
            low[u] = min(low[u],dfn[j]);
        }
    }
    if(dfn[u]==low[u]){
        ++tot;
        do{
            ++num[scc[q[top]] = tot];
        }while(q[top--]!=u);
    }
}
vector<int>g[N];
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        add(x,y);
        add(y,x+n);
        add(x+n,y+n);
    }
    tarjan(1);
    for(int i=1;i<=n*2;i++){
        if(dfn[i]){
            for(int k=h[i];k;k=ne[k]){
                int j=e[k];
                if(scc[i]!=scc[j]){
                    g[scc[i]].push_back(scc[j]),++deg[scc[j]];
                }
            }
        }
    }
    int l=0,r=0;
    for(int i=1;i<=tot;i++){
        if(!deg[i]) q[r++] = i;
        f[i]=-0x3f3f3f3f;
    }
    while(l < r){
        int u= q[l++];
        if(u==scc[1]) f[u]=0;
        for(int i=0;i<g[u].size();i++){
            int v=g[u][i];
            if(!--deg[v]) q[r++] = v;
            f[v] = max(f[v],f[u]+num[v]);
        }
    }
    cout<<f[scc[n+1]];
    return 0;
}
复制代码

 

part 2:数据结构

主要还是在练线段树qwq

P4145 上帝造题的七分钟 2 / 花神游历各国

线段树的区间开方操作。

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=1e9+7,MAXN=1e5+10,MAXNODE=MAXN*4;
int N,M;
LL tmp[MAXN],sum[MAXNODE],maxv[MAXNODE];
inline void push_up(int x){
    sum[x]=sum[x<<1]+sum[x<<1|1];
    maxv[x]=max(maxv[x<<1],maxv[x<<1|1]);
}
void init(int x,int l,int r){
    if(l==r){
        sum[x]=maxv[x]=tmp[l];
        return;
    }
    int mid=(l+r)>>1;
    init(x<<1,l,mid);
    init(x<<1|1,mid+1,r);
    push_up(x);
}
LL query(int x,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr)
        return sum[x];
    int mid=(l+r)>>1;
    LL ret=0;
    if(ql<=mid)
        ret+=query(x<<1,l,mid,ql,qr);
    if(mid<qr)
        ret+=query(x<<1|1,mid+1,r,ql,qr);
    return ret;
}
void update(int x,int l,int r,int ql,int qr){
    if(l==r){
        maxv[x]=sqrt(maxv[x]);
        sum[x]=sqrt(sum[x]);
        return;
    }
    if(maxv[x]<=1)
        return;
    int mid=(l+r)>>1;
    if(ql<=mid&&maxv[x<<1]>1)
        update(x<<1,l,mid,ql,qr);
    if(mid<qr&&maxv[x<<1|1]>1)
        update(x<<1|1,mid+1,r,ql,qr);
    push_up(x);
}
int main(){
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
        scanf("%lld",tmp+i);
    init(1,1,N);
    scanf("%d",&M);
    for(int i=1,k,l,r;i<=M;i++){
        scanf("%d%d%d",&k,&l,&r);
        if(l>r)
            swap(l,r);
        if(k)
            printf("%lld\n",query(1,1,N,l,r));
        else
            update(1,1,N,l,r);
    }
    return 0;
}
复制代码

 

P4551 最长异或路径

一道01 trie好题!

复制代码
#include<bits/stdc++.h>
using namespace std;
//过了样例,如何评价? 
const int MAXN=100010;
int s[MAXN],trie[MAXN*31][2];
int n,tot;
struct edge{
    int to,w;
};
vector<edge> p[MAXN];

void dfs(int x,int fa){
    for(int i=0;i<p[x].size();i++){
        int nxt=p[x][i].to;
        if(nxt!=fa){
            s[nxt]=s[x]^p[x][i].w;
            dfs(nxt,x);
        }
    }
}

void insert(int val){
    int x=0;
    for(int i=(1<<30);i;i>>=1){
        int a=bool(val&i);
        if(!trie[x][a])
            trie[x][a]=++tot;
        x=trie[x][a];
    }
}

int find(int val){
    int ans=0;
    int x=0;
    for(int i=(1<<30);i;i>>=1){
        int a=bool(val&i);
        if(trie[x][!a]){
            //这里调了半天!/kk 
            ans+=i;
            x=trie[x][!a];
        }else{
            x=trie[x][a];
        }
    }
    //哪个大冤种忘记return了? 
    return ans;
}

int main(){
    cin>>n;
    int a,b,c;
    for(int i=1;i<n;++i){
        cin>>a>>b>>c;
        p[a].push_back((edge){b,c});
        p[b].push_back((edge){a,c});
    }
    dfs(1,-1);
    for(int i=1;i<=n;++i){
        insert(s[i]);
    }
    int ans=0;
    for(int i=1;i<=n;++i){
        ans=max(ans,find(s[i]));
        //cout<<find(s[i])<<' ';
    }
    cout<<ans;
    return 0;
}
复制代码

 

P6136 【模板】普通平衡树(数据加强版)

这里提供3种写法,研究了好久。

本来还想用01trie写的,但是不会后缀树,只能跑到84pts,不放丑陋的代码!

1.FHQ treap

复制代码
#include<bits/stdc++.h>
using namespace std;
//FHQ treap试试? 
#define int long long
const int N=4e6+5;
struct Node{
    int l, r;
    int key;
    int sz, v;
    #define ls tr[u].l
    #define rs tr[u].r
}tr[N];

int root, idx;

void pushup(int u){
    tr[u].sz=tr[ls].sz+tr[rs].sz+1;
}

int add(int v){
    ++idx;
    tr[idx].key=rand(), tr[idx].sz=1, tr[idx].v=v;
    return idx;
}

int merge(int x, int y){
    if(!x || !y) return x+y;
    if(tr[x].key>tr[y].key){
        tr[x].r=merge(tr[x].r, y);
        pushup(x);
        return x;
    }
    else{
        tr[y].l=merge(x, tr[y].l);
        pushup(y);
        return y;
    }
}

void split(int u, int val, int &x, int &y){
    if(!u) return x=y=0, void();
    if(tr[u].v<=val)
        x=u, split(rs, val, rs, y);
    else
        y=u, split(ls, val, x, ls);
    pushup(u);
}

void insert(int v){
    int x, y;
    split(root, v, x, y);
    root=merge(x, merge(add(v), y));
}

void remove(int v){
    int x, y, z;
    split(root, v, x, z);
    split(x, v-1, x, y);
    y=merge(tr[y].l, tr[y].r);
    root=merge(merge(x, y), z);
}

int val4rk(int v){
    int x, y;
    split(root, v-1, x, y);
    int res=tr[x].sz+1;
    root=merge(x, y);
    return res;
}

int rk4val(int k){
    int u=root;
    while(u){
        if(tr[ls].sz+1==k) return tr[u].v;
        else if(tr[ls].sz>=k) u=ls;
        else k-=tr[ls].sz+1, u=rs;
    }
    return -1;
}

int get_prev(int v){
    int x, y;
    split(root, v-1, x, y);
    int u=x;
    while(rs) u=rs;
    int res=tr[u].v;
    root=merge(x, y);
    return res;
}



int get_next(int v){
    int x, y;
    split(root, v, x, y);
    int u=y;
    while(ls) u=ls;
    int res=tr[u].v;
    root=merge(x, y);
    return res;
}

int n,m,tmp,x,op,last;
signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>x;
        insert(x);
    }
    
    for(int i=1;i<=m;i++)
    {
        //int tmp=last;
        cin>>op;
         cin>>x;
         x^=last;
        if(op==1) insert(x);
        else if(op==2) remove(x);
        else if(op==3) last = val4rk(x);
        else if(op==4) last = rk4val(x);
        else if(op==5) last = get_prev(x);
        else if(op==6) last = get_next(x);
        //if(i!=1){
        //    tmp=last;
        //}
        //else 
        
        if(op>=3) {
            tmp^=last;
            //printf("%d %d\n",last,tmp);
        }
    }
    cout<<tmp;
    
    
    return 0;
}
复制代码

2.splay

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000010;
int read()
{
    int ans = 0;
    char c = getchar(), last = ' ';
    while(c < '0' || c > '9') last = c, c = getchar();
    while(c >= '0' && c <= '9') ans = (ans << 1) + (ans << 3) + c - '0', c = getchar();
    if(last == '-') ans = - ans;
    return ans;
}
int ecnt;
struct tree
{
    int l, r, siz, rad, val;
}t[N<<2];
unsigned long long seed = 1;
int Rand()
{
    seed *= 260817;
    return int(seed);
}
void update(int cnt)
{
    t[cnt].siz = t[t[cnt].l].siz + t[t[cnt].r].siz + 1;
}

int New(int x)
{
    t[++ecnt].val = x;
    t[ecnt].rad = Rand();
    t[ecnt].siz = 1;
    return ecnt;
}

void split(int cnt, int k, int &x, int &y)
{
    if(!cnt)
    {
        x = y = 0;
        return;
    }
    if(t[cnt].val <= k)
    {
        x = cnt;
        split(t[cnt].r, k, t[cnt].r, y);
    }
    if(t[cnt].val > k)
    {
        y = cnt;
        split(t[cnt].l, k, x, t[cnt].l);
    }
    update(cnt);
}

int merge(int x, int y)
{
    if(x == 0) return y;
    if(y == 0) return x;
    if(t[x].rad <= t[y].rad)
    {
        t[x].r = merge(t[x].r, y);
        update(x);
        return x;
    }
    else if(t[x].rad > t[y].rad)
    {
        t[y].l = merge(x, t[y].l);
        update(y);
        return y;
    }
}

int kth(int cnt, int k)
{
    if(t[t[cnt].l].siz + 1 == k) return t[cnt].val;
    if(t[t[cnt].l].siz >= k) return kth(t[cnt].l, k);
    else return kth(t[cnt].r, k - t[t[cnt].l].siz - 1);
}

int n, m, rt;
int last = 0, ans = 0;

int main()
{
    scanf("%d%d", &n, &m);
    int x, y, z, k, opt;
    for(int i = 1; i <= n; i ++)
    {
        k = read();
        split(rt, k, x, y);
        rt = merge(merge(x, New(k)), y);
    }
    for(int i = 1; i <= m; i ++)
    {
        opt = read(), k = read();
        k ^= last;
        if(opt == 1) 
        {
            split(rt, k, x, y);
            rt = merge(merge(x, New(k)), y);
        }
        if(opt == 2)
        {
            split(rt, k, x, y);
            split(x, k - 1, x, z);
            z = merge(t[z].l, t[z].r);
            rt = merge(merge(x, z), y); 
        }
        if(opt == 3)
        {
            split(rt, k - 1, x, y);
            last = t[x].siz + 1;
            ans ^= last;
        //    printf("%lld\n", last);
            rt = merge(x, y);
        }
        if(opt == 4)
        {
            last = kth(rt, k);
            ans ^= last;
        //    printf("%lld\n", last);
        }
        if(opt == 5)
        {
            split(rt, k - 1, x, y);
            last = kth(x, t[x].siz);
            ans ^= last;
        //    printf("%lld\n", last);
            rt = merge(x, y);
        }
        if(opt == 6)
        {
            split(rt, k, x, y);
            last = kth(y, 1);
            ans ^= last;
        //    printf("%lld\n", last);
            rt = merge(x, y);
        }
    }
    printf("%d", ans);
}
复制代码

3.WBLT(最快)

复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e7;
const double A=1.0/3.0;
struct node{int l,r,size,c;}tr[2*N];
int len,root,sta[N],tp;
inline int ins(int l,int r)
{
    int now=tp?sta[tp--]:++len; 
    tr[now].l=l;tr[now].r=r;tr[now].c=tr[r].c;
    tr[now].size=tr[l].size+tr[r].size;return now;
}
inline void vclean(int x){sta[++tp]=x;tr[x].l=tr[x].r=tr[x].c=tr[x].size=0;}
inline void vcopy(int y,int x){tr[x].l=tr[y].l;tr[x].r=tr[y].r;tr[x].size=tr[y].size;tr[x].c=tr[y].c;}
inline int vnew(int c){int now=tp?sta[tp--]:++len;tr[now].size=1;tr[now].c=c;return now;}
inline void pushup(int x)
{
    int l=tr[x].l,r=tr[x].r;if(!tr[l].size)return;
    tr[x].c=tr[r].c;tr[x].size=tr[l].size+tr[r].size;
}
inline void rotate(int x,bool p)
{
    if(p)
    {
        int l=tr[x].l;
        tr[x].r=ins(tr[l].r,tr[x].r);
        tr[x].l=tr[l].l;vclean(l);
    }
    else
    {
        int r=tr[x].r;
        tr[x].l=ins(tr[x].l,tr[r].l);
        tr[x].r=tr[r].r;vclean(r);
    }
}
inline bool pd(int x){return((double)(min(tr[tr[x].l].size,tr[tr[x].r].size))>=A*(double)(tr[x].size));}
inline void maintain(int x)
{
    if(pd(x))return;
    rotate(x,tr[tr[x].l].size>tr[tr[x].r].size);
}
void add(int now,int x)
{
    if(tr[now].size==1)
    {
        tr[now].l=vnew(min(tr[now].c,x));
        tr[now].r=vnew(max(tr[now].c,x));
        pushup(now);return;
    }
    maintain(now);
    int l=tr[now].l,r=tr[now].r;
    if(x<=tr[l].c)add(l,x);else add(r,x);pushup(now);
}
void del(int now,int fa,int x)
{
    if(tr[now].size==1)
    {
        int newone=(tr[fa].l==now)?tr[fa].r:tr[fa].l;
        vcopy(newone,fa);vclean(now);vclean(newone);return;
    }
    maintain(now);
    int l=tr[now].l,r=tr[now].r;
    if(x<=tr[l].c)del(l,now,x);else del(r,now,x);pushup(now);
}
int findrank(int now,int x)
{
    if(tr[now].size==1)return 1;maintain(now);
    int l=tr[now].l,r=tr[now].r;
    if(x<=tr[l].c)return findrank(l,x);
    else return tr[l].size+findrank(r,x);
}
int findshuz(int now,int k)
{
    if(tr[now].size==k)return tr[now].c;
    maintain(now);int l=tr[now].l,r=tr[now].r;
    if(k<=tr[l].size)return findshuz(l,k);
    else return findshuz(r,k-tr[l].size);
}
int ans,last,opt,x;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    root=vnew(1<<30);
    for(int i=1;i<=n;i++){
        cin>>x;
        add(root,x);
    }
    for(int i=1;i<=m;i++)
    {
       
        scanf("%d%d",&opt,&x);
        x^=last;
        if(opt==1)add(root,x);
        else if(opt==2)del(root,0,x);
        else if(opt==3)last=findrank(root,x);
        else if(opt==4)last=findshuz(root,x);
        else if(opt==5)last=findshuz(root,findrank(root,x)-1);
        else last=findshuz(root,findrank(root,x+1));
        if(opt>=3) ans^=last;
    }
    cout<<ans;
    return 0;
}
复制代码

 

posted @   Miya555  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示
主题色彩