Gym .101879 USP Try-outs (寒假自训第七场)

B .Aesthetics in poetry

题意:给定N个数,(N<2000 ,a[i] <=1e9),让你找一个最大的K,使得N个数膜K的余数个数全都等于N/K个。

思路:我们找到N的因子,然后验证即可,复杂度O(N^2)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;
int a[maxn],N,ans=-1,num[maxn];
void get(int k)
{
    rep(i,0,k-1) num[i]=0;
    rep(i,1,N) num[a[i]%k]++;
    bool F=true;
    rep(i,0,k-1) if(num[i]!=N/k) F=false;
    if(!F) return ;
    if(ans==-1) ans=k;
    else ans=min(ans,k);
}
int main()
{
    scanf("%d",&N);
    rep(i,1,N) scanf("%d",&a[i]);
    for(int i=2;i*i<=N;i++){
        if(N%i==0) {
            get(i);
            if(i*i!=N) get(N/i);
        }
    }
    get(N);
    printf("%d\n",ans);
    return 0;
}

D .Maximizing Advertising

题意:给定二维平面上N个点,其中一些是w,一些是b,让你用两个不相交的矩阵把他们圈起来,一个统计w的个数,一个统计b的个数,使得和最大。

思路:其实就是用一根线把平面分成两个。 枚举分割线即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
struct node
{
    int x,y,tp;
}a[maxn];
int n,X[maxn],Y[maxn],vis1[maxn],vis2[maxn],sum1,sum2;
int gao(int tp,int m)
{
    memset(vis1,0,sizeof(vis1));
    memset(vis2,0,sizeof(vis2));
    if(tp==1)
    {
        for(int i=1;i<=n;i++)
        if(a[i].tp==1)vis1[a[i].x]++;
        else vis2[a[i].x]++;
    }
    else
    {
        for(int i=1;i<=n;i++)
        if(a[i].tp==1)vis1[a[i].y]++;
        else vis2[a[i].y]++;
    }
    int ans=0,res1=0,res2=0;
    for(int i=1;i<=m;i++)
    {
        res1+=vis1[i],res2+=vis2[i];
        ans=max(ans,res1+sum2-res2);
        ans=max(ans,res2+sum1-res1);
    }
    return ans;
}
int main()
{
    char c[2];
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%s",&X[i],&Y[i],c);
        if(c[0]==‘b‘)a[i].tp=1,sum1++;
        else a[i].tp=2,sum2++;
        a[i].x=X[i],a[i].y=Y[i];
    }
    sort(X+1,X+1+n);
    int sz1=unique(X+1,X+1+n)-X-1;
    sort(Y+1,Y+1+n);
    int sz2=unique(Y+1,Y+1+n)-Y-1;
    for(int i=1;i<=n;i++)
    {
        a[i].x=lower_bound(X+1,X+1+sz1,a[i].x)-X;
        a[i].y=lower_bound(Y+1,Y+1+sz2,a[i].y)-Y;
    }
    int ans=gao(1,sz1);
    ans=max(ans,gao(2,sz2));
    printf("%d\n",ans);
}

E .Group work

题意:给定N个人,问有多少种分组情况,满足这个组至少有两人。

思路:即C(N,2)+C(N,3)+..C(N,N); 直接暴力即可, 也可以用2^N-C(N,1)-C(N,0);

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=110;
ll C[maxn][maxn],ans;
int main()
{
    rep(i,0,40) C[i][i]=C[i][0]=1;
    rep(i,1,40)
     rep(j,1,i)
     C[i][j]=C[i-1][j]+C[i-1][j-1];
    int N; scanf("%d",&N);
    rep(i,2,N) ans+=C[N][i];
    printf("%lld\n",ans);
    return 0;
}

G .Running a penitentiary

题意:给定N个区间[Li,Ri],然后Q次询问,每次给出a,b,问a到b这几个区间的公共长度是多少。

思路:开始还以为要主席树找区间的公共部分,但是发现既然是a到b的区间都有,那么公共部分因为的[b的最大值,a的最小值]。所以离散一下,线段树即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;
const int inf=1000000000;
int Mx[maxn],Mn[maxn];
void update1(int Now,int L,int R,int pos,int val)
{
    if(L==R) { Mn[Now]=val; return ;}
    int Mid=(L+R)>>1;
    if(pos<=Mid) update1(Now<<1,L,Mid,pos,val);
    else update1(Now<<1|1,Mid+1,R,pos,val);
    Mn[Now]=min(Mn[Now<<1],Mn[Now<<1|1]);
}
int query1(int Now,int L,int R,int l,int r)
{
    if(l<=L&&r>=R) return Mn[Now];
    int Mid=(L+R)>>1,res=inf;
    if(l<=Mid) res=min(res,query1(Now<<1,L,Mid,l,r));
    if(r>Mid) res=min(res,query1(Now<<1|1,Mid+1,R,l,r));
    return res;
}
void update2(int Now,int L,int R,int pos,int val)
{
    if(L==R){ Mx[Now]=val;return ;}
    int Mid=(L+R)>>1;
    if(pos<=Mid) update2(Now<<1,L,Mid,pos,val);
    else update2(Now<<1|1,Mid+1,R,pos,val);
    Mx[Now]=max(Mx[Now<<1],Mx[Now<<1|1]);
}
int query2(int Now,int L,int R,int l,int r)
{
    if(l<=L&&r>=R) return Mx[Now];
    int Mid=(L+R)>>1,res=-inf;
    if(l<=Mid) res=max(res,query2(Now<<1,L,Mid,l,r));
    if(r>Mid) res=max(res,query2(Now<<1|1,Mid+1,R,l,r));
    return res;
}
int main()
{
    int N,M,P,L,R; char opt[4];
    scanf("%d%d",&N,&M);
    rep(i,1,N<<2) Mn[i]=inf,Mx[i]=-inf;
    rep(i,1,N){
        scanf("%d%d",&L,&R);
        update1(1,1,N,i,R);
        update2(1,1,N,i,L);
    }
    rep(i,1,M){
        scanf("%s",opt);
        if(opt[0]==‘?‘){
            scanf("%d%d",&L,&R);
            int mn=query1(1,1,N,L,R);
            int mx=query2(1,1,N,L,R);
            printf("%d\n",max(mn-mx+1,0));
        }
        else {
            scanf("%d%d%d",&P,&L,&R);
            update1(1,1,N,P,R);
            update2(1,1,N,P,L);
        }
    }
    return 0;
}

J .Meme Wars

题意:字符串操作,每次F(x)=F(x-1)+‘x‘+F(x-1);问26次操作后,第N位是什么。(N<1000)

思路:因为N不大,所以我们保留前面N位,模拟即可。复杂度(N^2)

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1010;
char c[maxn][maxn]; int L[maxn],N;
int main()
{
    scanf("%d",&N);
    c[1][1]=‘a‘; L[1]=1;
    rep(i,2,27) {
        L[i]=L[i-1];
        rep(j,1,L[i]) c[i][j]=c[i-1][j];
        if(L[i]+1<=N) L[i]++,c[i][L[i]]=‘a‘+i-1;
        rep(j,1,L[i-1]) {
            if(L[i]+1>N) break;
            c[i][++L[i]]=c[i][j];
        }
    }
    printf("%c\n",c[27][N]);
    return 0;
}

H .Wine Production

题意:给定N个数,Q次询问,每次询问一个区间最大的x,满足至少x个不同的数出现了x次。(N,Q<3e4)

思路:跑莫队,然后记录每个数的个数。  问题是是莫队之后怎么维护这个答案。 我们用num[i]表示i出现的次数,cnt[i]表示出现次数为i的个数。 这样很难维护到有效信息,因为每次求答案的时候还是得x=1,=2..一个一个验证。    转化一下,cnt[i]表示出现次数大于等于i的个数,就可以莫队的时候直接转移答案了。 比如我加入一个数fcy, 那么num[fcy]++; cnt[num[fcy]]++;(而不用去cnt[num[fcy]-1]--;)因为出现次数大于等于num[fcy]-1的个数没变。 而加入fcy时,答案ans可能不变,可能变成了ans++变为了, cnt[num[fcy]]; 减去一个数fcy时也一样,ans可能不变,可能--;  想象成一个栈,如果操作中间,那么每次得重新维护这个栈。 而只操作栈顶,那么有效信息最多改变1,方便我们去维护。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;
const int inf=1000000000;
int a[maxn],b[maxn],cnt[maxn],num[maxn];
int ans[maxn],tot,B,res;
struct qust{
    int l,r,id;
    bool friend operator<(qust w,qust v){
        if(w.r/B==v.r/B) return w.l<v.l;
        return w.r<v.r;
    }
}q[maxn];
void add(int x,int tp)
{
    if(tp==-1){ cnt[num[x]]--; num[x]+=tp;  if(cnt[res]<res) res--;}
    else { num[x]+=tp;cnt[num[x]]++;if(cnt[num[x]]>=num[x]) res=max(res,num[x]);}
}
int main()
{
    int N,M;
    scanf("%d%d",&N,&M); B=300;
    rep(i,1,N) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+N+1); tot=unique(b+1,b+N+1)-(b+1);
    rep(i,1,N) a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
    rep(i,1,M) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
    sort(q+1,q+M+1);
    int L=1,R=0;
    rep(i,1,M){
        while(L<q[i].l) add(a[L++],-1);
        while(L>q[i].l) add(a[--L],1);
        while(R>q[i].r) add(a[R--],-1);
        while(R<q[i].r) add(a[++R],1);
        ans[q[i].id]=res;
    }
    rep(i,1,M) printf("%d\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/10352083.html

时间: 2024-07-30 14:00:42

Gym .101879 USP Try-outs (寒假自训第七场)的相关文章

Gym.101908 Brazil Subregional Programming Contest(寒假自训第六场)

这几天失眠时间都不太够,室友太会折腾了,感觉有点累,所以昨天的题解也没写,看晚上能不能补起来. B . Marbles 题意:给定N组数(xi,yi),玩家轮流操作,每次玩家可以选择其中一组对其操作,可以把它减去一个数,或同时减去一个数,当玩家操作后出现了(0,0)则胜利. 思路:注意这里是出现(0,0)胜,而不是全都是(0,0)胜,所以我们不能简单的球sg,最后异或得到答案. 但是我们转化一下,如果玩家面对的全是(1,2) 或(2,1),则他胜利,那么我们可以以这两个状态为起点得到sg函数,就

Gym -102007 :Benelux Algorithm Programming Contest (BAPC 18) (寒假自训第5场)

A .A Prize No One Can Win 题意:给定N,S,你要从N个数中选最多是数,使得任意两个之和不大于S. 思路:排序,然后贪心的选即可. #include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2000010; ll a[maxn]; int main() { int N,ans; l

Gym-101673 :East Central North America Regional Contest (ECNA 2017)(寒假自训第8场)

A .Abstract Art 题意:求多个多边形的面积并. 思路:模板题. #include<bits/stdc++.h> using namespace std; typedef long long ll; const double inf=1e200; const double eps=1e-12; const double pi=4*atan(1.0); int dcmp(double x){ return fabs(x)<eps?0:(x<0?-1:1);} struct

Gym102040 .Asia Dhaka Regional Contest(寒假自训第9场)

B .Counting Inversion 题意:给定L,R,求这个区间的逆序对数之和.(L,R<1e15) 思路:一看这个范围就知道是数位DP. 只是维护的东西稍微多一点,需要记录后面的各种数字的个数cnt,以及逆序对和sum,以及出现了多少种后缀num. 那么枚举到当前位时,假设为i ,那么sum+=cnt[i+1]+cnt[i+2]+....cnt[9];  cnt[i]+=num; 可以参考CF1073E. #include<bits/stdc++.h> #define rep(

(寒假开黑gym)2018 USP Try-outs

layout: post title: (寒假开黑gym)2018 USP Try-outs author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队! 许老师! B.Aesthetics in poetry (暴力模拟) #include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=

Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)

(本套题算是比较温和吧,就是罚时有点高. B .Baby Bites 题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组. 思路:从左往右依次固定,看是否有矛盾即可. #include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define rep2(i,a,b) for(int i=a;i>=b;i--) using n

Android寒假实训云笔记总结——欢迎页

欢迎页使用的是viewpager,需要适配器. 注意点: 1.判断是否是第一次进入这个app. 2.欢迎页小圆点的逻辑. 实现原理: 首先在activity_welcome放入viewpager和固定四个小圆点的图片在下方. viewpager用于存放多张欢迎页的图. welcome_selectoer用于当在哪一页对应的小圆点为灰色状态.即设置成不可点时状态为灰色. viewpager的内容为静态加载进去. 如图: 直接贴代码,代码都有注释:  WelcomeActivity.java pac

寒假特训——I - Fair

Some company is going to hold a fair in Byteland. There are nn towns in Byteland and mm two-way roads between towns. Of course, you can reach any town from any other town using roads. There are kk types of goods produced in Byteland and every town pr

寒假特训——搜索——H - Nephren gives a riddle

What are you doing at the end of the world? Are you busy? Will you save us? Nephren is playing a game with little leprechauns. She gives them an infinite array of strings, f0... ∞. f0 is "What are you doing at the end of the world? Are you busy? Will