• 20171006


        对于昨天的考试,可以说是把暴力分都拿到了

     T1 的搜索方式还是根据了这道题的性质,就是总的步数很少,然后再贪心的由小往大的更新,这样时间效率几乎就是O(N)的;想要做出来这道题,首先就是要分析出来

    往回走的步数其实是非常少的,至于如何分析出来,就可以直接打一个暴力,用一些时间搞出一些大数据的答案,然后再结合一下倍增的性质,应该就可以分析出来,然后就是如何去搜索,再搜索的时候,往往是和贪心减枝有紧密联系的,对于这道题,就是用小的步数去尽可能的更新多的点,然后之后枚举的步数就只用关注未确定步数的点

     T2的话,是一个莫比乌斯反演,其实这道题的暴力的极限应该是40分,但是当时还是不太懂μ做容斥系数的原理,这个可以做到√N的时间效率得到答案;今天又好好学习了一下莫比乌斯反演,不是那么的懵逼了,再莫比乌斯反演中,分块的思想可以大幅的提升时间效率,还是要做些题熟悉熟悉,具体的公式就不推了

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <iostream>
     6 #include <algorithm>
     7 using namespace std;
     8 # define maxN 30000010
     9 # define mod 76543
    10 typedef long long LL;
    11 LL n,N;
    12 int su[maxN],mu[maxN],tot;
    13 bool nosu[maxN];
    14 void Find_mu(){
    15     N=maxN-10;
    16     mu[1]=1;
    17     for(int i=2;i<=N;i++){
    18         if(!nosu[i]){
    19             su[++tot]=i; mu[i]=-1;
    20         }
    21         for(int j=1;j<=tot;j++){
    22             if((LL)i*su[j]>N) break;
    23             nosu[i*su[j]]=1;
    24             if(i%su[j]==0){mu[i*su[j]]=0; break;}
    25             mu[i*su[j]]=-mu[i];
    26         }
    27     }
    28     for(int i=1;i<=N;i++) mu[i]+=mu[i-1];
    29 }
    30 struct node{
    31     LL v,w; int nxt;
    32 }g[maxN/10];
    33 int adj[80010],e;
    34 void add(int u,LL v,LL w){
    35     g[e].v=v; g[e].w=w; g[e].nxt=adj[u];
    36     adj[u]=e++;
    37 }
    38 LL ps(LL x){
    39     if(x<=N) return mu[x];
    40     int k=x%mod;
    41     for(int i=adj[k];i!=-1;i=g[i].nxt)
    42         if(g[i].v==x) return g[i].w;
    43     LL ans=1; LL nxt;
    44     for(LL i=2;i<=x;i=nxt+1){
    45         nxt=(x/(x/i));
    46         ans-=(nxt-i+1)*ps(x/i);
    47     }
    48     add(k,x,ans);
    49     return ans;
    50 
    51 }
    52 LL find(LL i,LL j){
    53     return ps(j)-ps(i-1);
    54 }
    55 int main(){
    56     // freopen("123567_20.in","r",stdin);
    57     // freopen("666.out","w",stdout);
    58     scanf("%lld",&n);
    59     Find_mu();
    60     LL nxt; LL ans=0;
    61     memset(adj,-1,sizeof(adj));
    62     LL lim=sqrt(n);
    63     // ot();
    64     for(LL i=1;i<=lim;i=nxt+1){
    65         nxt=sqrt(n/(n/(i*i)));
    66         ans+=n/(i*i)*find(i,nxt); 
    67     }
    68     cout<<ans<<endl;
    69 }
    T2

    T3直接用Treap模拟可以拿到60,现在平衡树发现自己只会无旋Treap了,有时间要把Splay看一看,然后正解是线段树,就是利用平衡树中的中序遍历就是原序列,可以直接把一个平衡树拍成一个序列,然后可以发现,对于某一个点,他的左边的以他自己为起点上升序列长度+右边以他自己为起点上升序列长度,就是他的深度,为什么的话,可以找到,再这个序列中,一个点的左子树和右子树分别在这个点的左右两边,又因为这是一个大根堆,那么反过来,这个点可能在他的祖先(不一定是父亲)的右子树或者左子树,所以他的每一个祖先可能不再同一侧,而一个祖先有一定比他的孩子的权值大(大根堆),所以上升序列的长度和就是深度; 然后就是怎么用线段树维护这个上升序列,这个线段树里的update是递归实现的,这个之前没有遇到过,其实就是讨论一个子树中左右区间的影响关系,然后递归实现就行了,要注意的是合并子树信息是的顺序;还有一点两个点的LCA就是在序列中两个点之间的最大值(可以用最基本的线段树查询实现);

      1 #pragma GCC optimize("O3")
      2 #include <cmath>
      3 #include <cstdio>
      4 #include <ctime>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <iostream>
      8 #include <algorithm>
      9 # define maxn 200010
     10 using namespace std;
     11 void ot(){cout<<"******"<<endl;}
     12 struct QQ{
     13     int od,x,y;
     14 }q[maxn];
     15 typedef pair<int,int> D;
     16 D Max(D a,D b){return a.first>b.first? a:b;}
     17 int n,m,N;
     18 int hs[maxn];
     19 int ans1[4*maxn],ans2[4*maxn];
     20 D mx[4*maxn];
     21 bool cmp1(const int a,const int b){return a<b;}
     22 void lsan(){
     23     sort(hs+1,hs+N+1,cmp1);
     24     int cnt=unique(hs+1,hs+N+1)-hs-1;
     25     for(int i=1;i<=n;i++){
     26         if(q[i].od==2){
     27             q[i].x=lower_bound(hs+1,hs+cnt+1,q[i].x)-hs;
     28             q[i].y=lower_bound(hs+1,hs+cnt+1,q[i].y)-hs;
     29         }
     30         else q[i].x=lower_bound(hs+1,hs+cnt+1,q[i].x)-hs;
     31     }
     32     N=cnt;
     33 }
     34 void init(){
     35     scanf("%d",&n);
     36     for(int i=1;i<=n;i++){
     37         scanf("%d",&q[i].od);
     38         if(q[i].od==0){
     39             scanf("%d%d",&q[i].x,&q[i].y);
     40             hs[++N]=q[i].x;
     41         }
     42         if(q[i].od==1){
     43             scanf("%d",&q[i].x);
     44         }
     45         if(q[i].od==2){
     46             scanf("%d%d",&q[i].x,&q[i].y);
     47             if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
     48         }
     49     }
     50     lsan();
     51 }
     52 int cal1(int now,int l,int r,int h){
     53     if(l==r) return mx[now].first>h? 1:0;
     54     if(h>mx[now].first) return 0;
     55     int mid=(l+r)>>1;
     56     if(mx[now<<1].first<=h) return cal1(now<<1|1,mid+1,r,h);
     57     else return cal1(now<<1,l,mid,h)+ans1[now]-ans1[now<<1];
     58 }
     59 int cal2(int now,int l,int r,int h){
     60     if(l==r) return mx[now].first>h? 1:0;
     61     if(h>mx[now].first) return 0;
     62     int mid=(l+r)>>1;
     63     if(mx[now<<1|1].first<=h) return cal2(now<<1,l,mid,h);
     64     else return cal2(now<<1|1,mid+1,r,h)+ans2[now]-ans2[now<<1|1];
     65 }
     66 void change(int ch,int now,int l,int r,int num){
     67     if(l==r){
     68         ans1[now]=ans2[now]=1; mx[now]=D(num,l); return;
     69     }
     70     int mid=(l+r)>>1;
     71     if(ch<=mid) change(ch,now<<1,l,mid,num);
     72     if(ch>mid) change(ch,now<<1|1,mid+1,r,num);
     73     mx[now]=max(mx[now<<1],mx[now<<1|1]);
     74     ans1[now]=ans1[now<<1]+cal1(now<<1|1,mid+1,r,mx[now<<1].first);
     75     ans2[now]=ans2[now<<1|1]+cal2(now<<1,l,mid,mx[now<<1|1].first);
     76 }
     77 D query3(int left,int right,int now,int l,int r){
     78     if(left<=l && r<=right) return mx[now];
     79     int mid=(l+r)>>1;
     80     D ret;
     81     if(left<=mid) ret=max(ret,query3(left,right,now<<1,l,mid));
     82     if(right>mid) ret=max(ret,query3(left,right,now<<1|1,mid+1,r));
     83     return ret;
     84 }
     85 struct RRR{
     86     int ans,rt,l,r,mx;
     87     RRR(int a = 0,int b = 0,int c = 0,int d = 0,int e = 0){
     88         ans=a; rt=b; l=c; r=d; mx=e;
     89     }
     90 };
     91 RRR Mer1(RRR a,RRR b){
     92     if(a.ans==-1) return b;
     93     if(b.ans==-1) return a;
     94     RRR ret; 
     95     ret.mx=max(a.mx,b.mx);
     96     ret.ans=a.ans+cal1(b.rt,b.l,b.r,a.mx);
     97     return ret;
     98 }
     99 RRR query1(int left,int right,int now,int l,int r){
    100     if( left<=l && r<=right){ 
    101         return RRR(ans1[now],now,l,r,mx[now].first);
    102     }
    103     int mid=(l+r)>>1;
    104     RRR a,b,ret; a.ans=-1,b.ans=-1;
    105     if(left<=mid) a=query1(left,right,now<<1,l,mid);
    106     if(right>mid) b=query1(left,right,now<<1|1,mid+1,r);
    107     ret=Mer1(a,b);
    108     return ret;
    109 }
    110 RRR Mer2(RRR a,RRR b){
    111     if(a.ans==-1) return b;
    112     if(b.ans==-1) return a;
    113     RRR ret;
    114     ret.mx=max(a.mx,b.mx);
    115     ret.ans=b.ans+cal2(a.rt,a.l,a.r,b.mx);
    116     return ret;
    117 }
    118 RRR query2(int left,int right,int now,int l,int r){
    119     if(left<=l && r<=right){ return RRR(ans2[now],now,l,r,mx[now].first);}
    120     int mid=(l+r)>>1;
    121     RRR a,b,ret; a.ans=-1,b.ans=-1;
    122     if(right>mid) b=query2(left,right,now<<1|1,mid+1,r);
    123     if(left<=mid) a=query2(left,right,now<<1,l,mid);
    124     return Mer2(a,b);
    125     return ret;
    126 }
    127 void work(){
    128     for(int i=1;i<=n;i++){
    129         if(q[i].od==0){
    130             change(q[i].x,1,1,N,q[i].y);
    131             // cout<<q[i].x<<endl;
    132         }
    133         if(q[i].od==1){
    134             change(q[i].x,1,1,N,0);
    135         }
    136         if(q[i].od==2){
    137             // printf("pos== %d %d
    ",q[i].x,q[i].y );
    138             int dx=query1(q[i].x,N,1,1,N).ans+query2(1,q[i].x,1,1,N).ans;  //query1(q[i].x,N,1,1,N).ans+
    139             int dy=query1(q[i].y,N,1,1,N).ans+query2(1,q[i].y,1,1,N).ans;
    140             int k=query3(q[i].x,q[i].y,1,1,N).second;
    141             int dl=query1(k,N,1,1,N).ans+query2(1,k,1,1,N).ans;
    142             // printf("ans== %d %d
    ",ans1[1],ans2[1]);
    143             // printf("k= %d
    ",k);
    144             // printf("dep== %d %d %d
    ",dx,dy,dl);
    145             printf("%d
    ",dx+dy-2*dl);
    146         }
    147         // if(i==5) exit(0);
    148     }
    149 }
    150 int main(){
    151     // freopen("treap_1.in","r",stdin);
    152     // freopen("666.out","w",stdout);
    153     init();
    154     work();
    155 }
    View Code
  • 相关阅读:
    面向对象第三次总结性博客
    面向对象程序设计lesson2心得体会
    面向对象程序设计先导课程心得体会
    面向对象程序设计先导lesson1心得体会
    Git 学习笔记
    asp.net 的Eval日期時間怎麼格式化
    正則表達式(轉)
    要等彈出窗口顯示信息後,点击确定再跳轉到其他頁面
    彈出窗口,確定再刪除數據
    SQL SERVER 2008中的兩種潛換字符方法
  • 原文地址:https://www.cnblogs.com/FOXYY/p/7634406.html
Copyright © 2020-2023  润新知