zoukankan      html  css  js  c++  java
  • BZOJ4942【noi2017】整数

    luogu的题面

    https://www.luogu.org/problemnew/show/P3822

    题意:
         x初始为0,维护+a*2^k ,其中a为整数,k为自然数;查询x的第k位;

    题解:
        ①将数看成序列,线段树逐位维护。比较大,压位(下面的代码base=30,ls()
    rs()为左右儿子)。

        ②输入1,a,b,即将b/base号节点加 (a<<b%base)的base位以内部分,b/base+1号节点加 (a<<b%base)base位以上的部分。

        ③假设我们已经找到了b对应的叶子节点,修改后考虑进位。定义fg1[k]表示k节点是否是最大值(1<<base)-1,b对应的叶子往上跳一层到k号节点,如果fg1[rs(k)]==false,直接rs(k)里进位就好了,否则把rs(k)清零,再往上跳,退位同理(写的时候记得pushdown和pushup 。。。。TAT);

     

      1 #pragma GCC optimize(2)
      2 #include<cstdio>
      3 #include<iostream>
      4 //#define N 1000100
      5 //#define base 30
      6 #define ll long long
      7 #define ls(k) (k<<1)
      8 #define rs(k) (ls(k)|1) 
      9 using namespace std;
     10 const ll base=30,N=4.2e7/base,B=(1<<base)-1,len=4.1e7/base;
     11 //const int B = (1<<base) - 1,len = 1e6 + 5;
     12 int n,t1,t2,t3;
     13 int w[N<<2],fg1[N<<2],fg0[N<<2],ly1[N<<2],ly0[N<<2];
     14 char gc(){
     15     static char *p1,*p2,s[1000000];
     16     if(p1==p2) p2=(p1=s)+fread(s,1,1000000,stdin);
     17     return(p1==p2)?EOF:*p1++;
     18 }
     19 int rd(){
     20     int x = 0,f = 1; char c = gc();
     21     while(c<'0'||c>'9') {if(c=='-') f = -1; c = gc();}
     22     while(c>='0'&&c<='9') {x = x * 10 + c - '0'; c = gc();}
     23     return x * f;
     24 }
     25 void pushup(int k){
     26     int l = ls(k),r = rs(k);
     27     fg0[k] = fg0[l] && fg0[r];
     28     fg1[k] = fg1[l] && fg1[r];
     29 }
     30 void mdf(int k,int typ){
     31     w[k] = B * typ;
     32     fg1[k] = ly1[k] = typ; 
     33     fg0[k] = ly0[k] = !typ;
     34 }
     35 void pushdown(int k){
     36     int l = ls(k),r = rs(k);
     37     if(ly0[k]) mdf(l,0),mdf(r,0),ly0[k] = 0;
     38     if(ly1[k]) mdf(l,1),mdf(r,1),ly1[k] = 0;    
     39 }
     40 void change(int k,int l,int r,int typ){
     41     if(l==r) {
     42         w[k]+=typ;
     43         fg0[k]  = !w[k];
     44         fg1[k]  = (w[k]==B);
     45     }
     46     else{
     47         if(ly0[k]||ly1[k]) pushdown(k); 
     48         int mid = (l+r)>>1;
     49         if(typ==1){
     50             if(!fg1[ls(k)]) change(ls(k),l,mid,1); 
     51             else mdf(ls(k),0),change(rs(k),mid+1,r,1);
     52         }
     53         else{
     54             if(!fg0[ls(k)]) change(ls(k),l,mid,-1);
     55             else mdf(ls(k),1),change(rs(k),mid+1,r,-1);
     56         }
     57         pushup(k);
     58     }
     59 }
     60 int update(int k,int l,int r,int x,int y){
     61     if(!y) return 0;
     62     int typ = 0;
     63     if(l==r) {
     64         w[k] += y;
     65         if(w[k]>=(1<<base)) w[k] -= (1<<base),typ = 1;
     66         else if(w[k]<0) w[k] += (1<<base),typ = -1;
     67         fg0[k]  = !w[k];
     68         fg1[k]  = (w[k]==B);
     69     }
     70     else {
     71         if(ly0[k]||ly1[k]) pushdown(k);
     72         int mid = (l + r)>>1;
     73         if(x<=mid){
     74             typ = update(ls(k),l,mid,x,y);
     75             if(typ==1) {
     76                 if(!fg1[rs(k)]) typ = 0,change(rs(k),mid+1,r,1);
     77                 else mdf(rs(k),0);
     78             }
     79             if(typ==-1){
     80                 if(!fg0[rs(k)]) typ = 0,change(rs(k),mid+1,r,-1);
     81                 else mdf(rs(k),1);
     82             }
     83         }
     84         else typ = update(rs(k),mid+1,r,x,y);
     85         pushup(k);
     86     }
     87     return typ;
     88 }
     89 int query(int k,int l,int r,int x,int y){
     90     if(l==r) return bool(w[k]&y);
     91     else {
     92         if(ly0[k]||ly1[k]) pushdown(k);
     93         int mid = (l + r)>>1;
     94         if(x<=mid) return query(ls(k),l,mid,x,y);
     95         else return query(rs(k),mid+1,r,x,y);
     96     }
     97 }
     98 int main()
     99 {    //freopen("mzoj1111.in","r",stdin);
    100     //freopen("mzoj1111.out","w",stdout);
    101     n = rd(); t1 = rd(); t2 = rd(); t3 = rd();
    102     fg0[1] = ly0[1] = 1;
    103     for(int i = 1;i <= n;i++){
    104         ll opt = rd(),f,a,b,x,y;
    105         if(opt&1){
    106             a = rd(); b = rd();
    107             if(a<0) a*=-1,f=-1; else f=1;
    108             a <<= (b%base); b /= base;
    109             update(1,0,len,b,f*(a&B));
    110             update(1,0,len,b+1,f*(a>>base));
    111         }
    112         else{
    113             x = rd();
    114             y = 1<<(x%base); x /= base; 
    115             int ans = query(1,0,len,x,y);
    116             printf("%d
    ",ans);
    117         }
    118     }
    119     return 0;
    120 }//by tkys_Austin;

     

     

  • 相关阅读:
    使用std::accumulate计算和、积和平均值
    Boost文件读写,断言、日期
    mem_fun的用法,以及使用wcout
    singleton的内存泄漏及线程安全性问题
    delphi关键字
    Windows Api的一些方法 封装 以及 常用参数
    linux字符设备驱动 自动创建设备节点的的方法
    Linux混杂设备注册方法
    linux2.6字符设备的标准注册方法
    另一种linux下的powerpc中断注册的方法
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/8580239.html
Copyright © 2011-2022 走看看