2 条题解

  • 0
    @ 2025-10-8 16:55:31

    C53 可持久化线段树+离散化 P2464 [SDOI2008] 郁闷的小 J

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 10;
    #define lc(p) tr[p].ls
    #define rc(p) tr[p].rs
    #define mid ((l+r)>>1)
    int a[N], lsh[N * 2], cnt;
    struct node{int opt, l, r, p, id;/*id:书的编码*/} q[N];
    struct treenode{int ls, rs, siz/*区间数的个数*/;} tr[N*20];
    int trlen, rt[N];
    
    void pushup(int p){ tr[p].siz = tr[lc(p)].siz + tr[rc(p)].siz; }
    
    void change(int &now, int l, int r, int p, int k)// 点修
    { 
        if (!now) now = ++trlen;
        if (l == r){ tr[now].siz += k; return; }
        if (p <= mid) change(lc(now), l, mid, p, k);
        else change(rc(now), mid + 1, r, p, k);
        pushup(now);
    }
    int query(int now, int l, int r, int x, int y)// 区查
    { 
        if (x <= l && r <= y) return tr[now].siz;
        int s = 0;
        if (x <= mid) s += query(lc(now), l, mid, x, y);
        if (y > mid) s += query(rc(now), mid + 1, r, x, y);
        return s;
    }
    int main()
    {
        int n, m; scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]), lsh[i] = a[i]; // 保存书的编号
        cnt = n;
        for (int i = 1; i <= m; i++)// 保存操作
        { 
            char s[2]; scanf("%s", s);
            if (s[0] == 'C') q[i].opt = 0, scanf("%d%d", &q[i].p, &q[i].id);
            else q[i].opt = 1, scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].id);
            lsh[++cnt] = q[i].id; // 保存书的编号
        }
        sort(lsh + 1, lsh + cnt + 1);
        int ln = unique(lsh + 1, lsh + cnt + 1) - lsh - 1; // 去重
        trlen = 0;
        for (int i = 1; i <= n; i++)
        {
            a[i] = lower_bound(lsh + 1, lsh + ln + 1, a[i]) - lsh; // 编码变成离散值
            change(rt[a[i]], 1, n, i, 1); // 按离散值建可持久化线段树
        }
        for (int i = 1; i <= m; i++)// 处理操作
        { 
            if (!q[i].opt)// 更换图书
            { 
                change(rt[a[q[i].p]], 1, n, q[i].p, -1);
                a[q[i].p] = lower_bound(lsh + 1, lsh + ln + 1, q[i].id) - lsh;
                change(rt[a[q[i].p]], 1, n, q[i].p, 1);
            }
            else // 查询某编码的书的个数
            {
                int id = lower_bound(lsh + 1, lsh + ln + 1, q[i].id) - lsh;
                printf("%d\n", query(rt[id], 1, n, q[i].l, q[i].r));
            }
        }
        return 0;
    }
    
    • 0
      @ 2025-10-8 16:55:20

      C53 可持久化线段树+离散化 P2464 [SDOI2008] 郁闷的小 J

      #include <bits/stdc++.h>
      using namespace std;
      const int N = 1e5 + 10;
      #define lc(p) tr[p].ls
      #define rc(p) tr[p].rs
      #define mid ((l+r)>>1)
      int a[N], lsh[N * 2],cnt;
      struct node{int opt, l, r,p, id;/id:书的编码/} q[N];
      struct treenode{int ls,rs,siz/区间数的个数/;}tr[N*20];int trlen,rt[N];

      void pushup(int p){ tr[p].siz=tr[lc(p)].siz+tr[rc(p)].siz;}

      void change(int &now, int l, int r, int p, int k)// 点修 { if (!now)now=++trlen; if (l == r){tr[now].siz+= k;return;} if (p <= mid) change(lc(now), l, mid, p, k); else change(rc(now), mid + 1, r, p, k); pushup(now); } int query(int now, int l, int r, int x, int y)// 区查 { if(x<=l && r<=y)return tr[now].siz; int s=0; if(x<=mid)s+= query(lc(now), l, mid, x, y); if(y>mid) s+= query(rc(now), mid+1, r, x, y); return s; } int main() { int n,m;scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++)scanf("%d", &a[i]),lsh[i] = a[i]; // 保存书的编号 cnt=n; for (int i = 1; i <= m; i++)// 保存操作 { char s[2];scanf("%s", s); if(s[0]=='C') q[i].opt = 0, scanf("%d%d", &q[i].p, &q[i].id); else q[i].opt = 1, scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].id); lsh[++cnt] = q[i].id; // 保存书的编号 } sort(lsh+1, lsh+cnt+1); int ln = unique(lsh+1, lsh+cnt+1) - lsh - 1; // 去重 trlen=0; for (int i = 1; i <= n; i++) { a[i] = lower_bound(lsh+1,lsh+ln+1,a[i]) - lsh; // 编码变成离散值 change(rt[a[i]], 1, n, i, 1); // 按离散值建可持久化线段树 } for (int i = 1; i <= m; i++)// 处理操作 { if (!q[i].opt)// 更换图书 { change(rt[a[q[i].p]], 1, n, q[i].p, -1); a[q[i].p] = lower_bound(lsh+1,lsh+ln+1,q[i].id) - lsh; change(rt[a[q[i].p]], 1, n, q[i].p, 1); } else // 查询某编码的书的个数 { int id = lower_bound(lsh + 1, lsh + ln + 1, q[i].id) - lsh; printf("%d\n", query(rt[id], 1, n, q[i].l, q[i].r)); } } return 0; }</pre>

      • 1

      C53【可持久化线段树+离散化】区间x个数查询+带修改 [SDOI2008] 郁闷的小 J

      信息

      ID
      1095
      时间
      100ms
      内存
      128MiB
      难度
      7
      标签
      递交数
      161
      已通过
      32
      上传者