• 数据结构讲题选做


    //下面内容请选择性阅读

    一些胡乱的感受:

    抽 象 主 义 解 题

    充分让我认识到了我的码力有多么弱

    我真是对力量一无所知

    *你妈的,随便伤害无辜少年*

    维护维护维护维护维护维护

    猫不仅喜欢上树,还喜欢上数据结构

    sto immortalco orz

    — —好了,还有什么人要提问

    — —我要!

    — —什么?

    — —我写乱搞淦猫式上树树上问题,好吗

    — —好!

    *激烈的调试大赛*

    //正文开始了

    CodePlus 2018 3 月赛 寻找车位

    线段树神仙题

    什么,我的题解?去看i207M的吧

      1 // luogu-judger-enable-o2
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N=4e6+60,inf=1e9;
      7 int n,m,q,t1,t2,t3,t4,typ,len[N*4];
      8 struct a
      9 {
     10     int arr[N*4];
     11     int* operator[] (int x)
     12     {
     13         return arr+x*m;
     14     }
     15 }mapp,upp,low,mat;
     16 struct Mono_queue
     17 {
     18     int f,b,que[N];
     19     int* arr;
     20     int Size(){return b-f+1;}
     21     int Front(){return arr[que[f]];}
     22     void Init(int* ar){f=0,b=-1,arr=ar;}
     23     void Pop(int x){while(f<=b&&que[f]<=x) f++;}
     24     void Push(int x){while(f<=b&&arr[x]<=arr[que[b]]) b--;que[++b]=x;}
     25 };
     26 int Calc(int x,int y,int l,int r)
     27 {
     28     int ret=0;
     29     static Mono_queue q1,q2;
     30     q1.Init(upp[x]),q2.Init(low[y]);
     31     for(int b=l,f=l;b<=r;b++)
     32     {
     33         q1.Push(b),q2.Push(b);
     34         while(q1.Size()&&q2.Size()&&f<=b&&q1.Front()+q2.Front()<b-f+1)
     35             q1.Pop(f),q2.Pop(f),f++;
     36         ret=max(ret,b-f+1);
     37     }
     38     int *a1=upp[x],*a2=upp[y];
     39     for(int i=l;i<=r;i++) a1[i]=(a2[i]==len[y])?a1[i]+len[y]:a2[i];
     40     len[x]+=len[y];
     41     return ret;
     42 }
     43 void Pushup(int p,int x,int y)
     44 {
     45     static Mono_queue q1,q2;
     46     q1.Init(upp[x]),q2.Init(low[y]);
     47     int *a1=mat[p],*a2=mat[x],*a3=mat[y];
     48     for(int b=1,f=1;b<=m;b++)
     49     {
     50         q1.Push(b),q2.Push(b);
     51         while(q1.Size()&&q2.Size()&&f<=b&&q1.Front()+q2.Front()<b-f+1)
     52             q1.Pop(f),q2.Pop(f),f++;
     53         a1[b]=max(b-f+1,max(a2[b],a3[b]));
     54     }
     55     a1=upp[p],a2=upp[x],a3=upp[y];
     56     for(int i=1;i<=m;i++) a1[i]=(a3[i]==len[y])?a2[i]+len[y]:a3[i];
     57     a1=low[p],a2=low[x],a3=low[y];
     58     for(int i=1;i<=m;i++) a1[i]=(a2[i]==len[x])?a3[i]+len[x]:a2[i];
     59     len[p]=len[x]+len[y];
     60 }
     61 void Create(int nde,int l,int r)
     62 {
     63     if(l==r)
     64     {
     65         len[nde]=1;
     66         for(int i=1;i<=m;i++)
     67             upp[nde][i]=low[nde][i]=mapp[l][i];
     68     }
     69     else
     70     {
     71         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     72         Create(ls,l,mid),Create(rs,mid+1,r),Pushup(nde,ls,rs);
     73     }
     74 }
     75 void Change(int nde,int l,int r,int pos,int tsk)
     76 {
     77     if(l==r)
     78         mapp[l][tsk]^=1,upp[nde][tsk]=low[nde][tsk]=mapp[l][tsk];
     79     else
     80     {
     81         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     82         if(pos<=mid) Change(ls,l,mid,pos,tsk);
     83         else Change(rs,mid+1,r,pos,tsk); Pushup(nde,ls,rs);
     84     }
     85 }
     86 int Query(int nde,int l,int r,int nl,int nr,int ml,int mr)
     87 {
     88     if(l>=nl&&r<=nr)
     89     {
     90         int ret=Calc(0,nde,ml,mr);
     91         int *arr=mat[nde];
     92         for(int i=ml;i<=mr;i++)
     93             ret=max(ret,min(arr[i],i-ml+1));
     94         return ret;
     95     }
     96     else
     97     {
     98         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1,ret=0;
     99         if(mid>=nl) ret=max(ret,Query(ls,l,mid,nl,nr,ml,mr));
    100         if(mid<nr) ret=max(ret,Query(rs,mid+1,r,nl,nr,ml,mr));
    101         return ret;
    102     }
    103 }
    104 int main()
    105 {
    106     scanf("%d%d%d",&n,&m,&q);
    107     for(int i=1;i<=n;i++)
    108         for(int j=1;j<=m;j++)
    109             scanf("%d",&mapp[i][j]);
    110     Create(1,1,n);
    111     while(q--)
    112     {
    113         scanf("%d%d%d",&typ,&t1,&t2);
    114         if(!typ) Change(1,1,n,t1,t2);
    115         else
    116         {
    117             scanf("%d%d",&t3,&t4);
    118             for(int i=1;i<=m;i++) upp[0][i]=0; len[0]=0;
    119             printf("%d
    ",Query(1,1,n,t1,t3,t2,t4));
    120         }
    121     }
    122     return 0;
    123 }
    View Code

    清华集训 2016 数据交互

    两条链有交当且仅当有一条链的LCA在另一条链上,动态DP

    被卡常了,卡了一会,没卡过去,懒得卡了

    什么,我的题解?去看这位神仙的吧

      1 #include<set>
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<cstring>
      5 #include<algorithm>
      6 using namespace std;
      7 const int N=100005;
      8 int n,m,t1,t2,rd,cnt,tot;
      9 long long laz[4*N],val[4*N]; char str[10];
     10 int p[N],noww[2*N],goal[2*N],u[N],v[N],w[N],endp[N];
     11 int siz[N],far[N],dep[N],imp[N],top[N],dfn[N],ori[N];
     12 multiset<long long> st,ss[N]; 
     13 struct a
     14 {
     15     long long ll,rr,mx,sum;
     16 }seg[4*N];
     17 a operator + (a x,a y)
     18 {
     19     a ret;
     20     ret.ll=max(x.ll,x.sum+y.ll);
     21     ret.rr=max(y.rr,y.sum+x.rr);
     22     ret.mx=max(max(x.mx,y.mx),x.rr+y.ll);
     23     ret.sum=x.sum+y.sum; return ret;
     24 }
     25 void Read(int &x)
     26 {
     27     x=0; char ch=getchar();
     28     while(!isdigit(ch))
     29         ch=getchar();
     30     while(isdigit(ch))
     31         x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
     32 } 
     33 void Link(int f,int t)
     34 {
     35     noww[++cnt]=p[f];
     36     goal[cnt]=t,p[f]=cnt;
     37     noww[++cnt]=p[t];
     38     goal[cnt]=f,p[t]=cnt;
     39 }
     40 void DFS(int nde,int fth,int dth)
     41 {
     42     int tmp=0;
     43     siz[nde]=1,far[nde]=fth,dep[nde]=dth;
     44     for(int i=p[nde];i;i=noww[i])
     45         if(goal[i]!=fth)
     46         {
     47             DFS(goal[i],nde,dth+1);
     48             siz[nde]+=siz[goal[i]];
     49             if(siz[goal[i]]>tmp)
     50                 tmp=siz[goal[i]],imp[nde]=goal[i];
     51         }
     52 }
     53 void Mark(int nde,int tpp)
     54 {
     55     top[nde]=tpp,dfn[nde]=++tot;
     56     endp[nde]=dfn[nde],ori[tot]=nde;
     57     if(imp[nde])
     58     {
     59         Mark(imp[nde],tpp);
     60         endp[nde]=endp[imp[nde]];
     61         for(int i=p[nde];i;i=noww[i])
     62             if(goal[i]!=far[nde]&&goal[i]!=imp[nde])
     63                 ss[nde].insert(0),Mark(goal[i],goal[i]);
     64     }
     65     else st.insert(0);
     66 }
     67 int LCA(int x,int y)
     68 {
     69     while(top[x]!=top[y])
     70     {
     71         if(dep[top[x]]<dep[top[y]])
     72             swap(x,y); x=far[top[x]];
     73     }
     74     return dep[x]<dep[y]?x:y;
     75 }
     76 void Release(int nde)
     77 {
     78     if(laz[nde])
     79     {
     80         int ls=2*nde,rs=2*nde+1,lz=laz[nde];
     81         laz[ls]+=lz,seg[ls].rr+=lz,seg[ls].mx+=lz;
     82         laz[rs]+=lz,seg[rs].rr+=lz,seg[rs].mx+=lz;
     83         laz[nde]=0;
     84     }
     85 }
     86 a Query(int nde,int l,int r,int ll,int rr)
     87 {
     88     if(l>=ll&&r<=rr)
     89         return seg[nde];
     90     else
     91     {
     92         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
     93         if(mid>=rr) return Query(ls,l,mid,ll,rr);
     94         else if(mid<ll) return Query(rs,mid+1,r,ll,rr);
     95         else return Query(ls,l,mid,ll,rr)+Query(rs,mid+1,r,ll,rr);
     96     }
     97 }
     98 void Ex(int nde,int l,int r,int pos,long long tsk)
     99 {
    100     if(l==r)
    101     {
    102         int orn=ori[l]; long long ret=0;
    103         val[nde]+=tsk,seg[nde].sum=val[nde];
    104         multiset<long long> ::iterator it=ss[orn].end();    
    105         if(ss[orn].size()>=1) ret+=*(--it);
    106         seg[nde].ll=val[nde]+ret,seg[nde].rr=val[nde]+ret+laz[nde];
    107         if(ss[orn].size()>=2) ret+=*(--it);
    108         seg[nde].mx=val[nde]+ret+laz[nde];
    109     }
    110     else
    111     {
    112         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
    113         if(pos<=mid) Ex(ls,l,mid,pos,tsk);
    114         else Ex(rs,mid+1,r,pos,tsk); seg[nde]=seg[ls]+seg[rs];
    115     }
    116 }
    117 void Exc(int nde,int l,int r,int ll,int rr,int tsk)
    118 {
    119     if(l>rr||r<ll)
    120         return;
    121     else if(l>=ll&&r<=rr)
    122         seg[nde].rr+=tsk,seg[nde].mx+=tsk,laz[nde]+=tsk;
    123     else
    124     {
    125         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde);
    126         Exc(ls,l,mid,ll,rr,tsk),Exc(rs,mid+1,r,ll,rr,tsk);
    127         seg[nde]=seg[ls]+seg[rs];
    128     }
    129 }
    130 void Modify(int nde,long long val,int lca,int tsk)
    131 {
    132     while(nde)
    133     {
    134         int l=lca?max(dfn[top[nde]],dfn[lca]+1):n+1;
    135         int r=dfn[nde],nxt=far[top[nde]];
    136         if(nxt)
    137         {
    138             a x=Query(1,1,n,dfn[top[nxt]],endp[nxt]);
    139             st.erase(st.lower_bound(x.mx));
    140             ss[nxt].erase(ss[nxt].lower_bound(val)),val=x.ll;
    141         }
    142         if(l<=r)
    143         {
    144             st.erase(st.lower_bound(Query(1,1,n,dfn[top[nde]],endp[nde]).mx));
    145             Exc(1,1,n,l,r,tsk),st.insert(Query(1,1,n,dfn[top[nde]],endp[nde]).mx);
    146         }
    147         if(nxt)
    148         {
    149             ss[nxt].insert(Query(1,1,n,dfn[top[nde]],endp[nde]).ll);
    150             Ex(1,1,n,dfn[nxt],0),st.insert(Query(1,1,n,dfn[top[nxt]],endp[nxt]).mx);
    151         }
    152         nde=nxt;
    153     }
    154 }
    155 void Change(int u,int v,int w)
    156 {
    157     int lca=LCA(u,v);
    158     Modify(u,Query(1,1,n,dfn[top[u]],endp[u]).ll,lca,w);
    159     Modify(v,Query(1,1,n,dfn[top[v]],endp[v]).ll,lca,w);
    160     a x=Query(1,1,n,dfn[top[lca]],endp[lca]);
    161     st.erase(st.lower_bound(x.mx)),Ex(1,1,n,dfn[lca],w);
    162     st.insert(Query(1,1,n,dfn[top[lca]],endp[lca]).mx);
    163     Modify(lca,x.ll,0,0);
    164 }
    165 int main()
    166 {
    167     Read(n),Read(m);
    168     for(int i=1;i<n;i++) Read(t1),Read(t2),Link(t1,t2);
    169     DFS(1,0,1),Mark(1,1);
    170     for(int i=1;i<=m;i++)
    171     {
    172         scanf("%s",str);
    173         if(str[0]=='+') 
    174         {
    175             Read(u[i]),Read(v[i]),Read(w[i]);
    176             Change(u[i],v[i],w[i]);
    177         }
    178         else
    179             Read(rd),Change(u[rd],v[rd],-w[rd]);
    180         printf("%lld
    ",*st.rbegin());
    181     }
    182     return 0;
    183 }
    View Code

    UOJ #207 共价大爷游长沙

    日,发现自己的LCT写的又是假的

    学习了LCT维护子树信息:记录一个所有轻儿子的信息合并进去,具体来说要改改Access和Link

    一条路径被所有路径经过,当前仅当以一个端点为根时,所有路径的端点都恰好有一个在另一个的子树中

    我们每次把两个端点异或一个随机数,同时记录所有随机数的全集异或和,每次查询子树里异或和即可

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N=100005,M=300005;
      7 int n,m,t1,t2,t3,t4,typ,cnt,tot,fafa;
      8 int fth[N],son[N][2],rev[N],stk[N];
      9 int val[N],xors[N],lits[N],mem1[M];
     10 pair<int,int> mem2[M];
     11 void Read(int &x)
     12 {
     13     x=0; char ch=getchar();
     14     while(!isdigit(ch))
     15         ch=getchar();
     16     while(isdigit(ch))
     17         x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
     18 }
     19 void Write(int x)
     20 {
     21     if(x>9) Write(x/10);
     22     putchar(x%10^48);
     23 }
     24 int Rand()
     25 {
     26     return 1ll*rand()*rand()*rand()%2147483647;
     27 }
     28 void Pushup(int nde)
     29 {
     30     int lson=son[nde][0],rson=son[nde][1];
     31     xors[nde]=xors[lson]^xors[rson]^val[nde]^lits[nde];
     32 }
     33 void Release(int nde)
     34 {
     35     if(rev[nde])
     36     {
     37         int &lson=son[nde][0],&rson=son[nde][1];
     38         rev[lson]^=1,rev[rson]^=1,rev[nde]^=1;
     39         swap(lson,rson);
     40     }
     41 }
     42 bool Nottop(int nde)
     43 {
     44     int fa=fth[nde];
     45     return son[fa][0]==nde||son[fa][1]==nde;
     46 }
     47 void Rotate(int nde)
     48 {
     49     int fa=fth[nde],gr=fth[fa],isl=nde==son[fa][0];
     50     if(Nottop(fa)) son[gr][fa==son[gr][1]]=nde;
     51     fth[nde]=gr,fth[fa]=nde,fth[son[nde][isl]]=fa;
     52     son[fa][isl^1]=son[nde][isl],son[nde][isl]=fa;
     53     Pushup(fa),Pushup(nde);
     54 }
     55 void Splay(int nde)
     56 {
     57     int top=1; stk[top]=nde;
     58     for(int i=nde;Nottop(i);i=fth[i])
     59         stk[++top]=fth[i];
     60     while(top) Release(stk[top--]);
     61     while(Nottop(nde))
     62     {
     63         int fa=fth[nde],gr=fth[fa];
     64         if(Nottop(fa))
     65             Rotate(((son[fa][0]==nde)==(son[gr][0]==fa))?fa:nde);
     66         Rotate(nde);
     67     }
     68     Pushup(nde);
     69 }
     70 void Access(int nde)
     71 {
     72     int lst=0,mem=nde;
     73     while(nde)
     74     {
     75         Splay(nde);
     76         lits[nde]^=xors[son[nde][1]];
     77         lits[nde]^=xors[son[nde][1]=lst];
     78         Pushup(nde),lst=nde,nde=fth[nde];
     79     }
     80     Splay(mem);
     81 }
     82 void Turnroot(int nde)
     83 {
     84     Access(nde),rev[nde]^=1;
     85 }
     86 int Getroot(int nde)
     87 {
     88     Access(nde);
     89     while(son[nde][0])    
     90         nde=son[nde][0];
     91     Splay(nde);
     92     return nde;
     93 }
     94 void Split(int x,int y)
     95 {
     96     Turnroot(x),Access(y);
     97 }
     98 void Link(int x,int y)
     99 {
    100     Split(x,y),fth[x]=y,lits[y]^=xors[x],Pushup(y);
    101 }
    102 void Cut(int x,int y)
    103 {
    104     Split(x,y),fth[x]=son[y][0]=0,Pushup(y);
    105 }
    106 int Query(int x,int y)
    107 {
    108     Cut(x,y),Access(y);
    109     int ret=xors[y];
    110     Link(x,y);
    111     return ret;
    112 }
    113 void Change(int nde,int tsk)
    114 {
    115     Access(nde),val[nde]^=tsk,Pushup(nde);
    116 }
    117 int main()
    118 {
    119     srand(20020513);
    120     Read(fafa),Read(n),Read(m);
    121     for(int i=1;i<n;i++) 
    122         Read(t1),Read(t2),Link(t1,t2);
    123     while(m--)
    124     {
    125         Read(typ);
    126         if(typ==1)
    127         {
    128             Read(t1),Read(t2),Read(t3),Read(t4);
    129             Cut(t1,t2),Link(t3,t4);
    130         }
    131         else if(typ==2)
    132         {
    133             Read(t1),Read(t2),t3=Rand();
    134             Change(t1,t3),Change(t2,t3);
    135             tot^=t3,mem1[++cnt]=t3,mem2[cnt]=make_pair(t1,t2); 
    136         }
    137         else if(typ==3)
    138         {
    139             Read(t1),tot^=mem1[t1];
    140             Change(mem2[t1].first,mem1[t1]);
    141             Change(mem2[t1].second,mem1[t1]);
    142         }
    143         else 
    144         {
    145             Read(t1),Read(t2);
    146             Query(t1,t2)==tot?puts("YES"):puts("NO");
    147         }
    148     }
    149     return 0;
    150 }
    View Code

    PA 2014 Fiolki

    重构树,把所有步骤按时间连到虚点上,然后逆着扫求LCA,这样LCA深度越大的反应越早发生,模拟即可

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=400005,M=500005;
     6 struct a{int x,y,d,id;}sol[M];
     7 int n,m,k,t1,t2,cnt,tot; long long ans;
     8 int siz[N],anc[N],dep[N],imp[N],top[N];
     9 int p[N],noww[N<<1],goal[N<<1],bel[N],aset[N],g[N];
    10 bool cmp(a x,a y)
    11 {
    12     return x.d==y.d?x.id<y.id:x.d>y.d;
    13 }
    14 int Finda(int x)
    15 {
    16     return aset[x]==x?x:aset[x]=Finda(aset[x]);
    17 }
    18 void Link(int f,int t)
    19 {
    20     noww[++cnt]=p[f];
    21     goal[cnt]=t,p[f]=cnt;
    22     noww[++cnt]=p[t];
    23     goal[cnt]=f,p[t]=cnt;
    24 }
    25 void DFS(int nde,int fth,int dth)
    26 {
    27     int tmp=0;
    28     siz[nde]=1,anc[nde]=fth,dep[nde]=dth;
    29     for(int i=p[nde];i;i=noww[i])
    30         if(goal[i]!=fth)
    31         {
    32             DFS(goal[i],nde,dth+1);
    33             siz[nde]+=siz[goal[i]];
    34             if(siz[goal[i]]>tmp)
    35                 tmp=siz[goal[i]],imp[nde]=goal[i];
    36         }
    37 }
    38 void MARK(int nde,int tpp)
    39 {
    40     top[nde]=tpp;
    41     if(imp[nde])
    42     {
    43         MARK(imp[nde],tpp);
    44         for(int i=p[nde];i;i=noww[i])
    45             if(goal[i]!=anc[nde]&&goal[i]!=imp[nde])
    46                 MARK(goal[i],goal[i]);
    47     }
    48 }
    49 int LCA(int x,int y)
    50 {
    51     while(top[x]!=top[y])
    52     {
    53         if(dep[top[x]]<dep[top[y]])
    54             swap(x,y); x=anc[top[x]];
    55     }
    56     return dep[x]<dep[y]?x:y;
    57 }
    58 int main ()
    59 {
    60     scanf("%d%d%d",&n,&m,&k);
    61     for(int i=1;i<=n;i++) 
    62         scanf("%d",&g[i]),bel[i]=i,aset[i]=i;
    63     for(int i=1;i<=m;i++)
    64     {
    65         scanf("%d%d",&t1,&t2);
    66         Link(bel[t1],i+n),Link(bel[t2],i+n);
    67         bel[t2]=i+n,aset[Finda(t1)]=Finda(t2);
    68     }
    69     for(int i=n+m;i;i--)
    70         if(!siz[i]) DFS(i,0,1),MARK(i,i);
    71     for(int i=1;i<=k;i++)
    72     {
    73         scanf("%d%d",&t1,&t2);
    74         if(Finda(t1)==Finda(t2))
    75             sol[++tot]=(a){t1,t2,dep[LCA(t1,t2)],i};
    76     }
    77     sort(sol+1,sol+1+tot,cmp);
    78     for(int i=1;i<=tot;i++)
    79     {
    80         int tx=sol[i].x,ty=sol[i].y,mn=min(g[tx],g[ty]);
    81         g[tx]-=mn,g[ty]-=mn,ans+=2*mn;
    82     }
    83     printf("%lld",ans);
    84     return 0;
    85 }
    View Code

    PA 2014 Druzyny

    线线线段段段树树树题

    什么,我的题解?去看这位神仙的吧

    卡时空好题,加上BZOJ的评测机加持,刺激

    我这份代码卡着时空过的,如有需要请自行使用快读替换scanf等操作

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int N=1e6+10,M=4e6+20;
      6 const int inf=1e9,mod=1e9+7;
      7 int n,f,b,p,c[N],d[N],que[N],lpt[N],maxc[M];
      8 struct a
      9 {
     10     int opt,val;
     11 }dp[N],seg[M],laz[M];
     12 a Re(const a &x){return (a){x.opt+1,x.val};}
     13 void Add(int &x,int y){x+=y;if(x>=mod) x-=mod;}
     14 a operator + (a x,a y)
     15 {
     16     if(x.opt!=y.opt) return x.opt>y.opt?x:y;
     17     else {Add(x.val,y.val); return x;}
     18 }
     19 void Create2(int nde,int l,int r)
     20 {
     21     if(l==r)
     22         maxc[nde]=l;
     23     else
     24     {
     25         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     26         Create2(ls,l,mid),Create2(rs,mid+1,r);
     27            maxc[nde]=(c[maxc[ls]]<c[maxc[rs]])?maxc[rs]:maxc[ls];
     28     }
     29 }
     30 int Query2(int nde,int l,int r,int ll,int rr)
     31 {
     32     if(l>rr||r<ll)
     33         return 0;
     34     else if(l>=ll&&r<=rr)
     35         return maxc[nde];
     36     else
     37     {
     38         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     39         int r1=Query2(ls,l,mid,ll,rr);
     40         int r2=Query2(rs,mid+1,r,ll,rr);
     41         return c[r1]<c[r2]?r2:r1; 
     42     }
     43 }
     44 void Create3(int nde,int l,int r)
     45 {
     46     if(l==r)
     47         seg[nde]=dp[l],laz[nde]=(a){-inf,0};
     48     else
     49     {
     50         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     51         Create3(ls,l,mid),Create3(rs,mid+1,r);
     52         seg[nde]=seg[ls]+seg[rs],laz[nde]=laz[ls]+laz[rs];
     53     }
     54 }
     55 void Change3(int nde,int l,int r,int pos,a tsk)
     56 {
     57     if(l==r)
     58         seg[nde]=tsk;
     59     else
     60     {
     61         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     62         if(pos<=mid) Change3(ls,l,mid,pos,tsk);
     63         else Change3(rs,mid+1,r,pos,tsk);
     64         seg[nde]=seg[ls]+seg[rs];
     65     }
     66 } 
     67 void Add3(int nde,int l,int r,int ll,int rr,a tsk)
     68 {
     69     if(l>rr||r<ll)
     70         return ;
     71     else if(l>=ll&&r<=rr)
     72         laz[nde]=laz[nde]+tsk;
     73     else
     74     {
     75         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     76         Add3(ls,l,mid,ll,rr,tsk),Add3(rs,mid+1,r,ll,rr,tsk);    
     77     }
     78 } 
     79 a Query3(int nde,int l,int r,int pos)
     80 {
     81     a ret=(a){-inf,0};
     82     while(true)
     83     {
     84         ret=ret+laz[nde];
     85         if(l==r) return ret;
     86         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
     87         if(pos<=mid) nde=ls,r=mid; else nde=rs,l=mid+1;
     88     }
     89     return ret;
     90 }
     91 a Query4(int nde,int l,int r,int ll,int rr)
     92 {
     93     if(l>rr||r<ll)
     94         return (a){-inf,0};
     95     else if(l>=ll&&r<=rr)
     96         return seg[nde];
     97     else
     98     {
     99         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
    100         return Query4(ls,l,mid,ll,rr)+Query4(rs,mid+1,r,ll,rr); 
    101     }
    102 }
    103 int BS(int l,int r,int x)
    104 {
    105     int ret=0;
    106     while(l<=r)
    107     {
    108         int mid=(l+r)/2;
    109         if(lpt[mid]<=x) l=mid+1,ret=mid;
    110         else r=mid-1;
    111     }
    112     return ret;
    113 }
    114 void Solve(int l,int r,int k)
    115 {
    116     int mid=max(k,l+c[k]),ll=max(l,lpt[mid]),rr=min(k-1,mid-c[k]); 
    117     if(r<mid||k<=ll) return ;
    118     a qry=Query4(1,0,n,ll,rr); 
    119     while(ll<=l&&mid<=r)
    120     {
    121         if(k-1<=rr) 
    122         {
    123             int newr=BS(mid,r,l); 
    124             Add3(1,0,n,mid,newr,Re(qry)),mid=newr+1;
    125             break;
    126         }
    127         dp[mid]=dp[mid]+Re(qry);
    128         qry=qry+dp[++rr],ll=max(ll,lpt[++mid]);
    129     }
    130     while(mid<=r)
    131     {
    132         ll=lpt[mid],rr=min(k-1,mid-c[k]);
    133         if(k<ll) return ;
    134         a qur=Query4(1,0,n,ll,rr); 
    135         qur.opt++,dp[mid]=dp[mid]+qur,mid++;
    136     }
    137 }
    138 void Divide(int l,int r)
    139 {
    140     if(l>r) return;
    141     else if(l==r) 
    142     {
    143         dp[l]=dp[l]+Query3(1,0,n,l);
    144         Change3(1,0,n,l,dp[l]); return ;
    145     }
    146     else
    147     {
    148         int mid=Query2(1,0,n,l+1,r);
    149         Divide(l,mid-1),Solve(l,r,mid),Divide(mid,r);
    150     }
    151 }
    152 int main()
    153 {
    154     scanf("%d",&n),f=0,b=-1;
    155     for(int i=1;i<=n;i++)
    156         scanf("%d%d",&c[i],&d[i]);
    157     for(int i=1;i<=n;dp[i].opt=-inf,i++)
    158     {
    159         lpt[i]=lpt[i-1];
    160         while(f<=b&&d[i]<=d[que[b]]) b--;
    161         que[++b]=i;
    162         while(f<=b&&d[que[f]]+lpt[i]<i)
    163             f+=que[f]==lpt[i]+1,lpt[i]++; 
    164     }
    165     dp[0].val=1;
    166     Create2(1,0,n),Create3(1,0,n),Divide(0,n);
    167     (dp[n].opt>0)?printf("%d %d",dp[n].opt,dp[n].val):printf("NIE");
    168     return 0;
    169 } 
    View Code

    SCOI 2016 萌萌哒

    显然是并查集数联通块数cnt,然后答案是$9*10^{cnt-1}$(最高位填1-9,剩下的填0-9)

    ST表的思想,令$aset[i][j]$表示$[i,i+2^j-1]$这一块的连通性,递归合并,注意剪枝

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=100005,K=19,mod=1e9+7;
     7 int n,m,l1,l2,t1,t2,t3,t4,len,ans,aset[K][N];
     8 int Qpow(int x,int k)
     9 {
    10     if(k==1) return x;
    11     int tmp=Qpow(x,k/2);
    12     return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
    13 }
    14 int Finda(int o,int x)
    15 {
    16     return aset[o][x]==x?x:aset[o][x]=Finda(o,aset[o][x]);
    17 }
    18 void Merge(int a,int b,int k)
    19 {
    20     int f1=Finda(k,a),f2=Finda(k,b),len=1<<(k-1);
    21     aset[k][f1]=f2; if(!k||f1==f2) return; 
    22     Merge(a,b,k-1),Merge(a+len,b+len,k-1);
    23 }
    24 int main()
    25 {
    26     scanf("%d%d",&n,&m),l1=log2(n);
    27     for(int i=0;i<=l1;i++)
    28         for(int j=1;j<=n;j++)
    29             aset[i][j]=j;
    30     for(int i=1;i<=m;i++)
    31     {
    32         scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
    33         if(t1>t3) swap(t1,t3),swap(t2,t4);
    34         l2=log2(t2-t1+1),len=(1<<l2)-1;
    35         Merge(t1,t3,l2),Merge(t2-len,t4-len,l2);
    36     }
    37     for(int i=1;i<=n;i++)
    38         if(Finda(0,i)==i) ans++;
    39     printf("%lld",9ll*Qpow(10,ans-1)%mod);
    40     return 0;
    41 }
    View Code

    SCOI 2016 美味

    从高位向低位贪心,在主席树上二分找加上偏移量之后的区间里有没有值,有就贪心拿这一位

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=200005,inf=1e9,Maxx=(1<<18)-1;
     6 int n,m,t1,t2,t3,t4,tot;
     7 int dish[N],root[N],cnt[N*40],son[N*40][2];
     8 int Insert(int pre,int l,int r,int pos)
     9 {
    10     int nde=++tot;
    11     son[nde][0]=son[pre][0];
    12     son[nde][1]=son[pre][1];
    13     cnt[nde]=cnt[pre]+1;
    14     if(l!=r)
    15     {
    16         int mid=(l+r)>>1;
    17         if(pos<=mid) 
    18             son[nde][0]=Insert(son[pre][0],l,mid,pos);
    19         else 
    20             son[nde][1]=Insert(son[pre][1],mid+1,r,pos);
    21     }
    22     return nde;
    23 }
    24 int Query(int l,int r,int nl,int nr,int ll,int rr)
    25 {
    26     if(l>rr||r<ll) 
    27         return 0;
    28     else if(l>=ll&&r<=rr) 
    29         return cnt[nr]-cnt[nl];    
    30     else
    31     {
    32         int mid=(l+r)>>1;
    33         int r1=Query(l,mid,son[nl][0],son[nr][0],ll,rr);
    34         int r2=Query(mid+1,r,son[nl][1],son[nr][1],ll,rr);
    35         return r1+r2;
    36     }
    37 }
    38 int Ask(int l,int r,int ll,int rr,int k,int a,int b)
    39 {
    40     if(l==r) return a^l;
    41     int mid=(l+r)>>1;
    42     if(a&(1<<(k-1)))
    43     {
    44         int qry=Query(0,Maxx,ll,rr,max(l-b,0),max(mid-b,0));
    45         return qry?Ask(l,mid,ll,rr,k-1,a,b):Ask(mid+1,r,ll,rr,k-1,a,b);
    46     }
    47     else
    48     {
    49         int qry=Query(0,Maxx,ll,rr,max(mid+1-b,0),max(r-b,0));
    50         return qry?Ask(mid+1,r,ll,rr,k-1,a,b):Ask(l,mid,ll,rr,k-1,a,b);    
    51     }
    52 }
    53 int main()
    54 {
    55     scanf("%d%d",&n,&m);
    56     for(int i=1;i<=n;i++)
    57     {
    58         scanf("%d",&dish[i]);
    59         root[i]=Insert(root[i-1],0,Maxx,dish[i]);
    60     }
    61     while(m--)
    62     {
    63         scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
    64           printf("%d
    ",Ask(0,Maxx,root[t3-1],root[t4],18,t1,t2));
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    开启JAVA学习之旅 Day1
    python二分法及小tips
    简单的注入脚本
    Requests文档 阅读笔记
    多线程
    IO操作
    异常Exception
    Map集合
    Collection集合
    泛型
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10383998.html
Copyright © 2020-2023  润新知