zoukankan      html  css  js  c++  java
  • [考试反思]1008csp-s模拟测试64:契机

    暴力没打满。。。有点垃圾。。。

    考得稍绝望,啥也不会啊???

    T3的测试点分治还写挂了。。。

    其实就是没有沉下心好好的思考,在三道题上来回切换结果一个成型思路都没有

    T2既然已经想到那一步了居然没有继续想下去。。。

    不管怎么说,还是思路凌乱了,没有稳下来

    但是,也算是混进第一鸡房了,也是新的自我调整的机会吧

    没怎么颓废,改题也快了。。。感觉不错

    这是一个好的桌面背景。(Ubuntu Mono Bold Italic 150号字)

    T1:trade

    刚开始以为要怎么优化dp。但是这其实是一个比较明显的反悔型贪心。

    因为取消卖出和进行买入这两个操作本质是一样的,往堆里扔就是了。

    买a卖b再买b卖c,和买a卖c是等价的,这样就做到了反悔。

    当你决定卖的时候就往堆里扔一个用于反悔卖出这个决定。

    然后每个元素都还要往堆里扔一个来用于正常的买入。

    代码比暴力dp还好写。

     1 #include<cstdio>
     2 #include<queue>
     3 using namespace std;
     4 priority_queue<int,vector<int>,greater<int> >q;
     5 int n,x;long long ans;
     6 main(){
     7     scanf("%d%d",&n,&x);q.push(x);n--;
     8     while(n--){
     9         scanf("%d",&x);
    10         if(x>q.top())ans+=x-q.top(),q.pop(),q.push(x);
    11         q.push(x);
    12     }printf("%lld
    ",ans);
    13 }
    View Code

    思路积累:

    • 反悔型贪心:正确性证明与数据结构结合达到最优决策

    T2:sum

    根据定义,有S[i][j]=S[i][j-1]+C[i][j]

    打表发现,有S[i][j]=S[i-1][j-1]+S[i-1][j]

    用含义就可以知道:i个里至多选j个,随意指定其中一个元素,如果它选,那么就在剩下的i-1里至多选j-1个,如果它不选,那就在剩下的i-1里选至多j个

    合并一下,有S[i][j]=S[i-1][j]*2-C[i-1][j]

    这样的形式就可以做到O(1)的把数组的某一维变化1了。可以莫队了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 #define int long long
     5 #define mod 1000000007
     6 struct qs{int m,n,id;friend bool operator<(qs a,qs b){return a.n/400!=b.n/400?a.n/400<b.n/400:a.m/400<b.m/400;}}q[100005];
     7 int fac[100005],inv[100005],invv[100005],id,Q,n,m,ans[100005];
     8 int C(int b,int t){return b<t?0:fac[b]*inv[t]%mod*inv[b-t]%mod;}
     9 main(){//freopen("sum1.in","r",stdin);freopen("my.out","w",stdout);
    10     fac[0]=invv[1]=inv[1]=inv[0]=fac[1]=1;
    11     for(int i=2;i<=100000;++i)fac[i]=fac[i-1]*i%mod,invv[i]=mod-mod/i*invv[mod%i]%mod,inv[i]=inv[i-1]*invv[i]%mod;
    12     scanf("%lld%lld",&id,&Q);
    13     int x=1,y=1,Ans=2;
    14     for(int i=1;i<=Q;++i)scanf("%lld%lld",&q[i].n,&q[i].m),q[i].id=i;
    15     sort(q+1,q+1+Q);
    16     for(int i=1;i<=Q;++i){
    17         while(x<q[i].n)Ans=(Ans+Ans-C(x,y)+mod)%mod,++x;
    18         while(x>q[i].n)--x,Ans=(Ans+C(x,y))*500000004ll%mod;
    19         while(y<q[i].m)++y,Ans=(Ans+C(x,y))%mod;
    20         while(y>q[i].m)Ans=(Ans-C(x,y)+mod)%mod,--y;
    21         ans[q[i].id]=Ans;
    22     }for(int i=1;i<=Q;++i)printf("%lld
    ",ans[i]);
    23 }
    View Code

    思路积累:

    • 莫队和分块思路在递推表达式求值上的应用

    但是还是想讲一下自己傻逼的部分分想法:m全部相同的20分。

    $S_{n,m}=sumlimits_{i=0}^m C_{n,i} $

    $=sumlimits_{i=0}^m n! imes inv(i!) imes inv((n-i)!)$

    $= n! sumlimits_{i=0}^m inv(i!) imes inv((n-i)!) $

    然后后面就是一个比较明显的卷积形式了。

    因为求和只是到m为止,所以不能直接把两个inv套起来,对于第一个inv数组大于m的项赋成0就可以解决这个问题了。

    然后我们就能求出对于每一个n后面的那个卷积式了,就可以O(1)回答询问了。

    因为模数是1000000007,不是一个好的NTT模数,所以需要多模数CRT一发。

    思路还好,就是如果考场上我要是打这个的话可能就不用干别的了。

    又是用省选知识点打联赛暴力的好例子

    诚当是磨砺思维吧(虽然在考场上耽误了不少时间)

    T3:building

    loj差点就让我弃坑了。

    对于询问有多少个块,这还是比较好做的,差分一下O(1)修改,最后求两遍前缀和。

    至于联通块,容易想起以前的结论:在无环图上,联通块数=点数-边数

    然而这道题有环。我们把每一次操作作为一个点,把相邻的操作建边,求联通块。

    可以利用并查集,这样它就成了树型的了,就可以用点数-边数了。

    建边的时候,如果发现它们已经联通,那么就不再建边,这样就保证了无环。

    我的思路是横边只与横边相邻,竖边只与竖边有相邻。

    那么怎么考虑横边与竖边之间的相邻呢?

    可以发现如果横边与竖边相邻的话,其实就是其中的一条边与另一条边的某一个端点相邻。

    这样的话,我们在加入某一条横边的时候,同时也把它的两个端点当成竖边加入。加入竖边时同理。

    然后逐行扫,不断加入x1小的边即可。

    暴力的做法是爆扫相邻的两行/列枚举每一个块。这样的复杂度在极端时会被卡成n2

    但是本题没有卡可以AC,虽说跑的很慢而且我的方法有有3倍量的块。2900ms。

     1 #include<cstdio>
     2 #include<vector>
     3 #include<algorithm>
     4 #include<iostream>
     5 using namespace std;
     6 struct ps{int x1,x2,y1,y2,ord;friend bool operator<(ps a,ps b){return a.x1<b.x1;}}p[100005];
     7 vector<ps>L[100005],R[100005];
     8 int ans,cf[100005],f[100005],cb[100005],eds;
     9 int find(int k){return f[k]==k?k:f[k]=find(f[k]);}
    10 void link(int a,int b){
    11     int fa=find(a),fb=find(b);
    12     if(fa!=fb)eds++,f[fa]=fb;
    13 }
    14 int main(){
    15     int id,n,m,k,q,qk,qx,pt=1;scanf("%d%d%d%d%d",&id,&n,&m,&k,&q);
    16     for(int i=1,x1,x2,y1,y2;i<=k;++i){
    17         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    18         p[i]=(ps){x1,x2,y1,y2,f[i]=i};
    19         if(x1==x2)cf[x1]+=y2-y1+1,cf[x1+1]-=y2-y1+1;
    20         else cf[x1]++,cf[x2+1]--;
    21     }
    22     for(int i=1;i<=n;++i)cf[i]+=cf[i-1];
    23     for(int i=1;i<=n;++i)cf[i]+=cf[i-1];
    24     sort(p+1,p+k+1);
    25     for(int I=1;I<=n;cb[I]=pt-eds-1,++I)while(p[pt].x1==I&&pt<=k){
    26         int x1=p[pt].x1,x2=p[pt].x2,y1=p[pt].y1,y2=p[pt].y2,ord=p[pt].ord,X1=x1-1,X2=x2+1,Y1=y1-1,Y2=y2+1;
    27         for(int i=0;i<L[X1].size();++i)if(!(L[X1][i].y1>y2||L[X1][i].y2<y1))link(L[X1][i].ord,ord);
    28         for(int i=0;i<R[Y1].size();++i)if(!(R[Y1][i].x1>x2||R[Y1][i].x2<x1))link(R[Y1][i].ord,ord);
    29         for(int i=0;i<L[X2].size();++i)if(!(L[X2][i].y1>y2||L[X2][i].y2<y1))link(L[X2][i].ord,ord);
    30         for(int i=0;i<R[Y2].size();++i)if(!(R[Y2][i].x1>x2||R[Y2][i].x2<x1))link(R[Y2][i].ord,ord);
    31         ps P1=(ps){x1,x1,y1,y1,ord},P2=(ps){x2,x2,y2,y2,ord};
    32         if(y1==y2)R[y1].push_back(p[pt]),L[x2].push_back(P2),L[x1].push_back(P1);
    33         else L[x1].push_back(p[pt]),R[y2].push_back(P2),R[y1].push_back(P1);
    34         pt++;
    35     }
    36     while(q--)scanf("%d%d",&qk,&qx),printf("%d
    ",qk?cb[qx]:cf[qx]);
    37 }
    View Code

    肯定是可以优化的。一种是把vector改成set这样的话常数会非常大最后可能比暴力还慢。

    另一种就是先把所有边都加入然后sort,用lower_bound查询并及时break就行。

    要注意你建边时只与前面行的建边,没有扫到的行不要建。

    QAQnlog的代码还没有写等会马上跟上啊我没脸溜了

    QAQ打完超级长的nlog的正解了但是它跑的比暴力还慢啊啊啊常数这么丑2940ms但是好歹打正解了我又有脸了啊啊啊溜了

     1 #include<cstdio>
     2 #include<vector>
     3 #include<algorithm>
     4 #include<iostream>
     5 using namespace std;
     6 struct ps{int x1,x2,y1,y2,ord;friend bool operator<(ps a,ps b){return a.x1!=b.x1?a.x1<b.x1:a.y1<b.y1;}}p[100005];
     7 vector<ps>L[100005],R[100005];
     8 int ans,cf[100005],f[100005],cb[100005],eds;
     9 int find(int k){return f[k]==k?k:f[k]=find(f[k]);}
    10 void link(int a,int b){
    11     int fa=find(a),fb=find(b);//printf("link:%d %d
    ",a,b);
    12     if(fa!=fb)eds++,f[fa]=fb;
    13 }
    14 int main(){//freopen("building1.in","r",stdin);
    15     int id,n,m,k,q,qk,qx,pt=1;scanf("%d%d%d%d%d",&id,&n,&m,&k,&q);
    16     for(int i=1,x1,x2,y1,y2;i<=k;++i){
    17         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    18         p[i]=(ps){x1,x2,y1,y2,f[i]=i};
    19         ps P1=(ps){x1,x1,y1,y1,i},P2=(ps){x2,x2,y2,y2,i};
    20         if(x1==x2)cf[x1]+=y2-y1+1,cf[x1+1]-=y2-y1+1,L[x1].push_back(p[i]),R[y2].push_back(P2),R[y1].push_back(P1);
    21         else cf[x1]++,cf[x2+1]--,R[y1].push_back(p[i]),L[x2].push_back(P2),L[x1].push_back(P1);
    22     }
    23     for(int i=1;i<=n;++i)cf[i]+=cf[i-1];
    24     for(int i=1;i<=n;++i)cf[i]+=cf[i-1];
    25     for(int i=1;i<=n;++i)sort(L[i].begin(),L[i].end());
    26     for(int i=1;i<=m;++i)sort(R[i].begin(),R[i].end());
    27     sort(p+1,p+k+1);
    28     for(int I=1;I<=n;cb[I]=pt-eds-1,++I)while(p[pt].x1==I&&pt<=k){
    29         int x1=p[pt].x1,x2=p[pt].x2,y1=p[pt].y1,y2=p[pt].y2,ord=p[pt].ord,X1=x1-1,X2=x2+1,Y1=y1-1,Y2=y2+1;
    30         for(int i=max(0,lower_bound(L[X1].begin(),L[X1].end(),(ps){X1,X1,y1,y1,0})-L[X1].begin()-1);i<L[X1].size();++i)
    31             if(!(L[X1][i].y1>y2||L[X1][i].y2<y1)){if(L[X1][i].x1<=I)link(L[X1][i].ord,ord);}
    32             else if(L[X1][i].y1>y2)break;
    33         for(int i=max(0,lower_bound(R[Y1].begin(),R[Y1].end(),(ps){x1,x1,Y1,Y1,0})-R[Y1].begin()-1);i<R[Y1].size();++i)
    34             if(!(R[Y1][i].x1>x2||R[Y1][i].x2<x1)){if(R[Y1][i].x1<=I)link(R[Y1][i].ord,ord);}
    35             else if(R[Y1][i].x1>x2)break;
    36         for(int i=max(0,lower_bound(R[Y2].begin(),R[Y2].end(),(ps){x1,x1,Y2,Y2,0})-R[Y2].begin()-1);i<R[Y2].size();++i)
    37             if(!(R[Y2][i].x1>x2||R[Y2][i].x2<x1)){if(R[Y2][i].x1<=I)link(R[Y2][i].ord,ord);}
    38             else if(R[Y2][i].x1>x2)break;
    39         pt++;
    40     }
    41     while(q--)scanf("%d%d",&qk,&qx),printf("%d
    ",qk?cb[qx]:cf[qx]);
    42 }
    View Code

    思路积累:

    • 联通块的性质
    • 离线处理
  • 相关阅读:
    235. Lowest Common Ancestor of a Binary Search Tree
    112. Path Sum
    111. Minimum Depth of Binary Tree
    110. Balanced Binary Tree
    108. Convert Sorted Array to Binary Search Tree
    win7+iis7.5+asp.net 安装IIS 遇到的一些问题
    创建一个简单的WCF程序
    ROW_NUMBER() OVER函数的基本用法
    input type="file"
    Nightmare
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11636234.html
Copyright © 2011-2022 走看看