<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【CSP 202303-4】星際網絡Ⅱ 【離散化+線段樹】

      題目鏈接

      http://118.190.20.162/view.page?gpid=T162

      題意

      一個網絡地址由 \(n\) (\(n \leq 512\) ,且是16的倍數)位二進制位組成(形如 xxxx:xxxx: .... :xxxx),有若干用戶需要申請一些網絡地址。

      有三種操作:

      1. 申請。給出一個用戶編號,和要查詢的地址區間[L, R],若全都沒有被申請過,或者之前有一部分(不能是全部)被此用戶申請過,輸出YES,否則輸出NO
      2. 單點查詢。查詢某地址p,返回申請者的編號,沒有人申請過返回0
      3. 區間查詢。查詢地址區間[L, R]是否全部被某用戶申請過,若是返回申請者編號,否返回0

      一共有 \(q(q \leq 50000)\) 次操作

      思路

      20分做法

      \(n \leq 16,q \leq 200\),暴力枚舉即可

      100分做法

      別問,問就是其他做法我不會

      因為網絡地址的范圍很大($ \leq 2^{512}$),而詢問的數量是比較可觀的,因此可以想到離散化。

      這題的網絡地址有一個特點,就是如果當作字符串讀入的話,字符串的字典序和地址按照大小排列的順序一致;還有一點需要注意,如果離散化之前的區間是[1,2],[4,5],離散化之后會變成[1,2],[3,4],從不連續變成了連續的,所以在離散化的時候需要把區間右端點+1的位置也一起排序,注意+1導致的地址進位問題。

      具體步驟是先把網絡地址以字符串的形式全部讀入,直接用sort排好序,然后用lower_bound函數查找,用得到的下標給地址重新賦值

          cin >> n >> q;
          for(int i = 1; i <= q; i++) {
              cin >> op[i];
              if(op[i] == 1) {
                  cin >> id[i] >> l[i] >> r[i];
                  tem[++cnt] = l[i]; tem[++cnt] = r[i];
                  if(!s_f(r[i])) tem[++cnt] = nex(r[i]);
              }
              else if(op[i] == 2) {
                  cin >> s[i];
                  tem[++cnt] = s[i];
              }
              else {
                  cin >> l[i] >> r[i];
                  tem[++cnt] = l[i]; tem[++cnt] = r[i];
                  if(!s_f(r[i])) tem[++cnt] = nex(r[i]);
              }
          }
          sort(tem + 1, tem + cnt + 1);
          int k = unique(tem + 1, tem + cnt + 1) - tem - 1;
          build(1, 1, k);
          for(int i = 1; i <= q; i++) {
              if(op[i] == 1) {
                  L[i] = lower_bound(tem + 1, tem + k + 1, l[i]) - tem;
                  R[i] = lower_bound(tem + 1, tem + k + 1, r[i]) - tem;
                  int cnt = qry(1, 1, k, L[i], R[i]), mn = qry_min(1, 1, k, L[i], R[i]), mx = qry_max(1, 1, k, L[i], R[i]);
                  if(cnt == 0 || mn == mx && mn == id[i] && cnt < R[i] - L[i] + 1) {
                      cout << "YES\n";
                      upd(1, 1, k, L[i], R[i], id[i]);
                  }
                  else cout << "NO\n";
              }
              else if(op[i] == 2) {
                  L[i] = lower_bound(tem + 1, tem + k + 1, s[i]) - tem;
      			int ans = qry_max(1, 1, k, L[i], L[i]);
                  cout << ((ans > 0 && ans <= k) ? ans : 0) << endl;
              }
              else {
                  L[i] = lower_bound(tem + 1, tem + k + 1, l[i]) - tem;
                  R[i] = lower_bound(tem + 1, tem + k + 1, r[i]) - tem;
                  int cnt = qry(1, 1, k, L[i], R[i]), mn = qry_min(1, 1, k, L[i], R[i]), mx = qry_max(1, 1, k, L[i], R[i]);
                  if(mn == mx && cnt == R[i] - L[i] + 1 && mn > 0) cout << mn << endl;
                  else cout << 0 << endl;
              }
          }
      

      這樣就把范圍很大的地址映射到1e5量級了。

      因為操作涉及到區間,區間查詢、區間修改、單點查詢,很容易想到線段樹這一數據結構。

      用t[rt]代表一個樹上結點,v表示這個結點內被申請了的地址個數,mn mx代表申請了這塊地址范圍的申請人編號的最小值、最大值,lazy就是懶標記

      操作一:
      區間查詢
      YES的情況:v == 0 || (v < r - l + 1 && mn == mx && mn == id),然后還要upd這個區間的值為id
      否則是NO

      操作二:
      單點查詢p位置的編號

      操作三:
      區間查詢
      有答案的情況:mn == mx && mn > 0 && v == r - l + 1
      否則是0

      code

      #include<bits/stdc++.h>
      #define ll long long
      using namespace std;
      const int N = 2e5 + 10;
      int n, q, op[N], id[N], cnt, L[N], R[N];
      string l[N], r[N], s[N], tem[N << 1];
      struct SegTree{
          int v;   // 區間內被用過的值的個數
          int lazy;
          int mn, mx;  // 區間內最小 最大id
      }t[N << 2]; 
      
      void push_up(int rt) {
          t[rt].v = t[rt * 2].v + t[rt * 2 + 1].v;
      	t[rt].mn = min(t[rt * 2].mn, t[rt * 2 + 1].mn);
          t[rt].mx = max(t[rt * 2].mx, t[rt * 2 + 1].mx);
      }
      
      void build(int rt, int l, int r) {
          t[rt].lazy = 0; 
          if(l == r) {
              t[rt].v = 0;
              t[rt].mn = 1e9; t[rt].mx = -1e9;
              return;
          }
          int mid = (l + r) >> 1;
          build(rt * 2, l, mid);
          build(rt * 2 + 1, mid + 1, r);
          push_up(rt);
      }
      
      void push_down(int rt, int lenl, int lenr) {
          if(t[rt].lazy) {
              t[rt * 2].v = lenl;
              t[rt * 2 + 1].v = lenr;
              t[rt * 2].lazy = t[rt].lazy;
              t[rt * 2 + 1].lazy = t[rt].lazy;
              t[rt * 2].mn = t[rt * 2].mx = t[rt].lazy;
              t[rt * 2 + 1].mn = t[rt * 2 + 1].mx = t[rt].lazy;
              t[rt].lazy = 0;
          }
      }
      
      void upd(int rt, int l, int r, int L, int R, int v) {
          if(l > r || l > R || L > r) return;
          if(L <= l && r <= R) {
              t[rt].v = r - l + 1;
              t[rt].mn = t[rt].mx = v;
              t[rt].lazy = v;
              return;
          }
          int mid = (l + r) >> 1;
          push_down(rt, mid - l + 1, r - mid);
          upd(rt * 2, l, mid, L, R, v);
          upd(rt * 2 + 1, mid + 1, r, L, R, v);
          push_up(rt);
      }
      
      int qry_min(int rt, int l, int r, int L, int R) {
          if(l > r || l > R || L > r) return 1e9;
          if(L <= l && r <= R) return t[rt].mn;
          int mid = (l + r) >> 1;
          push_down(rt, mid - l + 1, r - mid);
          return min(qry_min(rt * 2, l, mid, L, R), qry_min(rt * 2 + 1, mid + 1, r, L, R));
      }
      
      int qry_max(int rt, int l, int r, int L, int R) {
          if(l > r || l > R || L > r) return -1e9;
          if(L <= l && r <= R) return t[rt].mx;
          int mid = (l + r) >> 1;
          push_down(rt, mid - l + 1, r - mid);
          return max(qry_max(rt * 2, l, mid, L, R), qry_max(rt * 2 + 1, mid + 1, r, L, R));
      }
      
      int qry(int rt, int l, int r, int L, int R) {
          if(l > r || l > R || L > r) return 0;
          if(L <= l && r <= R) return t[rt].v;
          int mid = (l + r) >> 1;
          push_down(rt, mid - l + 1, r - mid);
          return qry(rt * 2, l, mid, L, R) + qry(rt * 2 + 1, mid + 1, r, L, R);
      }
      
      inline bool s_f(string s) {
          for(auto ch : s) {
              if(ch == ':') continue;
              if(ch != 'f') return 0;
          }
          return 1;
      }
      
      inline string nex(string s) {
          bool f = 0;
          for(int i = s.length() - 1; i >= 0; i--) {
              if(s[i] == ':') continue;
              if(s[i] == 'f') s[i] = '0';
              else if(s[i] >= 'a') s[i] += 1, f = 1;
              else if(s[i] == '9') s[i] = 'a', f = 1;
              else s[i] += 1, f = 1;
              if(f) break;
          }
          return s;
      }
      
      int main() {
          ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
          cin >> n >> q;
          for(int i = 1; i <= q; i++) {
              cin >> op[i];
              if(op[i] == 1) {
                  cin >> id[i] >> l[i] >> r[i];
                  tem[++cnt] = l[i]; tem[++cnt] = r[i];
                  if(!s_f(r[i])) tem[++cnt] = nex(r[i]);
              }
              else if(op[i] == 2) {
                  cin >> s[i];
                  tem[++cnt] = s[i];
              }
              else {
                  cin >> l[i] >> r[i];
                  tem[++cnt] = l[i]; tem[++cnt] = r[i];
                  if(!s_f(r[i])) tem[++cnt] = nex(r[i]);
              }
          }
          sort(tem + 1, tem + cnt + 1);
          int k = unique(tem + 1, tem + cnt + 1) - tem - 1;
          // cout << "K: " << k << endl;  ////
          build(1, 1, k);
          for(int i = 1; i <= q; i++) {
              if(op[i] == 1) {
                  L[i] = lower_bound(tem + 1, tem + k + 1, l[i]) - tem;
                  R[i] = lower_bound(tem + 1, tem + k + 1, r[i]) - tem;
      //            cout << L[i] << ' ' << R[i] << endl;  //////
                  int cnt = qry(1, 1, k, L[i], R[i]), mn = qry_min(1, 1, k, L[i], R[i]), mx = qry_max(1, 1, k, L[i], R[i]);
      //            cout << cnt << ' ' << mn << ' ' << mx << endl;  ///
                  if(cnt == 0 || mn == mx && mn == id[i] && cnt < R[i] - L[i] + 1) {
                      // cout << ans.size() << ' ';
                      cout << "YES\n";
                      upd(1, 1, k, L[i], R[i], id[i]);
                  }
                  else cout << "NO\n";
              }
              else if(op[i] == 2) {
                  L[i] = lower_bound(tem + 1, tem + k + 1, s[i]) - tem;
      //            cout << L[i] << endl;  //////
      			int ans = qry_max(1, 1, k, L[i], L[i]);
                  cout << ((ans > 0 && ans <= k) ? ans : 0) << endl;
              }
              else {
                  L[i] = lower_bound(tem + 1, tem + k + 1, l[i]) - tem;
                  R[i] = lower_bound(tem + 1, tem + k + 1, r[i]) - tem;
      //            cout << L[i] << ' ' << R[i] << endl; ////
                  int cnt = qry(1, 1, k, L[i], R[i]), mn = qry_min(1, 1, k, L[i], R[i]), mx = qry_max(1, 1, k, L[i], R[i]);
      //            cout << cnt << ' ' << mn << ' ' << mx << endl;  ///
                  if(mn == mx && cnt == R[i] - L[i] + 1 && mn > 0) cout << mn << endl;
                  else cout << 0 << endl;
              }
          }
          return 0;
      }
      
      posted @ 2023-05-21 20:40  starlightlmy  閱讀(541)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 伊人欧美在线| 奶头好大揉着好爽视频| 亚洲成人四虎在线播放| 国产无遮挡裸体免费久久| 中文字幕日韩有码第一页| 扒开双腿猛进入喷水高潮叫声| 鹤庆县| 粉嫩一区二区三区国产精品| 福利视频一区二区在线| 亚洲av永久无码精品天堂久久| 久久99精品国产麻豆婷婷| 精品国产欧美一区二区五十路| 色综合色综合色综合频道| аⅴ天堂中文在线网| av高清无码 在线播放| 龙山县| 国产黑色丝袜在线播放| 狠狠v日韩v欧美v| 少妇愉情理伦片高潮日本| 久久热这里只有精品66| 乱码精品一区二区三区| 亚洲男人天堂东京热加勒比| 精品国产免费一区二区三区香蕉| 少妇xxxxx性开放| 国产精品国产三级国快看| 人妻日韩人妻中文字幕| 久热色精品在线观看视频| 日本视频精品一区二区| 国产精品香港三级国产av| 久久精品无码精品免费专区| 精品一卡2卡三卡4卡乱码精品视频| 精品尤物TV福利院在线网站| 最新亚洲精品国偷自产在线| 无码国产偷倩在线播放老年人| 国精产品一区一区三区有限公司杨| 国产成人精品一区二区不卡| 中文字幕国产精品日韩| 特级欧美AAAAAAA免费观看| 国产超碰人人爽人人做| 亚洲深深色噜噜狠狠网站| 香蕉乱码成人久久天堂爱|