zoukankan      html  css  js  c++  java
  • Codeforces Round #532 (Div. 2)

    A. Roman and Browser

    题意:给出k,让你求b,使所有位置c(c满足c = b + i * k) 的标签全部消失,使1和-1的数量相差最大,求b。

    枚举。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    int n,k;
    int aa,bb;
    int p;
    int v[110];
    int main(){
        while(cin>>n>>k)
        {
            p=1000*k;
            for(int i=1;i<=n;i++)
            {
                int u;
                cin>>v[i];
                if(v[i]>0)aa++;
                else bb++;
            }
            int ans=0;
            for(int b=1;b<=n;b++)
            {
                int xx=aa,yy=bb;
                for(int j=b-1;j>0;j--)
                {
                    if((b-j)%k==0)
                    {
                        if(v[j]>0)xx--;
                        else yy--;
                    }
                } 
                for(int j=b;j<=n;j++)
                {
                    if((j-b)%k==0)
                    {
                        if(v[j]>0)xx--;
                        else yy--;
                    }
                }
                ans=max(ans,abs(xx-yy));
            }
            cout<<ans<<endl;
        }
    }
    View Code

    B. Build a Contest

    题意:依次给出数字,当凑足了1-n时输出1,否则输出0。

    记录当前位置有几个数字了,凑满数字就所有vis(次数数组减一),一开始居然想到用线段树维护维护这个减一操作和查询次数,因为觉得n太大了每次都扫一遍会超时。后来发现,由于m时固定的,所以扫描n的次数最多是m/n次,每次要n的时间,所以就是o(m)的时间。所以暴力不会出事。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    int n,m;
    int a[maxn];
    int vis[maxn];
    string ans;
    int main(){
        while(cin>>n>>m)
        {
            CLR(vis,0);
            ans="";
            for(int i=1;i<=m;i++)
            {
                scanf("%d",&a[i]);
            }
            int tot=0;
            for(int i=1;i<=m;i++)
            {
                if(vis[a[i]]==0){
                    tot++;
                    vis[a[i]]=1;
                }else{
                    vis[a[i]]++;
                }
                if(tot<n)ans+="0";
                else{
                    ans+="1";
                    tot=0;
                    for(int j=1;j<=n;j++)
                    {
                        vis[j]--;
                        if(vis[j]>0)tot++;
                    }
                }
            }
            cout<<ans<<endl;
        }
    }
    View Code

    C. NN and the Optical Illusion

    初中计算几何题,设外半径为R,半径为r,可以列方程,会解二元一次方程就可以,直接套求根公式。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=100010;
    const double pai=acos(-1.0);
    double n,r,R,p,die;
    int main(){
        while(cin>>n>>r)
        {
            p=cos(2*pai/n);
        //    cout<<p<<endl;
            die=(4*r*p-4*r)*(4*r*p-4*r)-4*(2+2*p)*(2*r*r*p-2*r*r);
            double ans=((4*r-4*r*p)+sqrt(die))/(4+4*p);
            printf("%.8f
    ",ans);
        }
    }
    View Code

    D. Dasha and Chess

    交互题,学习了博客,题意好像又搞错了,看了博客后,代码就跟默写一样了……交互题还是不太会啊。

    就是要记住,方向数组的变化, i 和 j 对应的是y 和 x,不要弄反了。

    转一位大佬的博客,讲的很清晰。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=1e3+10;
    int fx[4][2]={{1,1},{1,-1},{-1,1},{-1,-1}};
    int vis[maxn][maxn],bx[680],by[680],u,px,py,x,y;
    int s1[10],s2[10];
    void Move(int xx,int yy){
        x+=xx;
        y+=yy;
        if(vis[x][y])x-=xx;
        printf("%d %d
    ",x,y);
        fflush(stdout);
        scanf("%d%d%d",&u,&px,&py);
        if(u==-1&&px==-1&&py==-1)exit(0);
        vis[bx[u]][by[u]]=0;
        vis[px][py]=1;
        bx[u]=px;
        by[u]=py;
        
    }
    int main(){
        cin>>x>>y;
        for(int i=1;i<=666;i++)
        {
            scanf("%d%d",&bx[i],&by[i]);
            vis[bx[i]][by[i]]=1;
        }
        while(x<500)Move(1,0);
        while(y<500)Move(0,1);
        while(x>500)Move(-1,0);
        while(y>500)Move(0,-1);
        for(int i=1;i<=499;i++) for(int j=1;j<=499;j++) if(vis[i][j]) s1[1]++;
        for(int i=1;i<=499;i++) for(int j=501;j<=999;j++) if(vis[i][j]) s1[2]++;
        for(int i=501;i<=999;i++) for(int j=1;j<=499;j++) if(vis[i][j]) s1[3]++;
        for(int i=501;i<=999;i++) for(int j=501;j<=999;j++) if(vis[i][j]) s1[4]++;
        s2[1]=s1[2]+s1[3]+s1[4];
        s2[2]=s1[1]+s1[3]+s1[4];
        s2[3]=s1[1]+s1[2]+s1[4];
        s2[4]=s1[1]+s1[2]+s1[3];
        int maxx=0,tep;
        for(int i=1;i<=4;i++)
        {
            if(s2[i]>maxx){
                maxx=s2[i];
                tep=i-1;
            }
        }
        while(true)
        {
            Move(fx[tep][0],fx[tep][1]);
        }
        
    }
    View Code

    E. Andrew and Taxi

    题意:给出一副有向图,每条边的权值是代表使这条边反向所需要的能力,现在希望使整幅图无环,并且只要使一条边反向了,其他所有权值小于等于这条边的边都可以免费反向。

    题解:显然是一个可以二分的题目,因为对所有边进行合法操作必然能得到一个合法的图,这个limit越小则限制越严格。

    对于一个二分出来的权值k,我们可以先把所有权值小于等于k的边全部取消,而其他边全部变成拓扑偏序关系,由于取消掉了这些边,所以这些边的影响相当于是最后由我决定的,只要我能写出合法的拓扑序列,那我按照这个拓扑序列来决定边的方向即可。合法的拓扑序列即拓扑完成后元素个数等于n(否则说明有环,元素还在队列里)。

    不断二分k,那怎么根据拓扑序列来决定边的方向呢?其实就是看每个元素的拓扑序号是多少,比如u和v,如果u有一条连向v的有向边,但u的拓扑序号却比v的拓扑序号大,说明在拓扑序列中,u在v的后面,所以这条边要被反向,即输出。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    int n,m;
    struct node{
        int u,v;
        ll w;
    };
    struct edge{
        int to,Next;
    }e[maxn];
    vector<node >a;
    int u,v,tot,head[maxn],d[maxn],top[maxn];
    ll w,l,r,mid; 
    void addv(int u,int v){
        e[++tot].to=v;
        e[tot].Next=head[u];
        head[u]=tot;
    }
    bool toposort(){
        queue<int >q;
        int cnt=0; 
        for(int i=1;i<=n;i++)
        {
            if(d[i]==0){
                q.push(i);
            }
        }
        while(!q.empty())
        {
            int u=q.front();
            top[u]=++cnt;
            q.pop();
            for(int i=head[u];i!=-1;i=e[i].Next)
            {
                int v=e[i].to;
                d[v]--;
                if(d[v]==0)
                {
                    q.push(v);
                }
            }
        }
        if(cnt==n)return true;
        return false;
    }
    void buildGraph(ll mid){
        clr(head,-1),tot=0;
        clr(d,0);
        for(int i=0;i<m;i++)
        {
            int st=a[i].u,ed=a[i].v;
            ll val=a[i].w;
            if(val>mid){
                addv(st,ed);
                d[ed]++;
            }
        }
    }
    vector<int >ans;
    int main(){
        while(cin>>n>>m)
        {
            a.clear();
            ans.clear();
            l=0,r=0;
            for(int i=0;i<m;i++)
            {
                scanf("%d%d%lld",&u,&v,&w);
                a.push_back({u,v,w});
                r=max(r,w);
            }
            while(l<r)
            {
                mid=(l+r)>>1;
                buildGraph(mid);
                if(toposort()){
                    r=mid;
                }else {
                    l=mid+1;
                }
            }
            buildGraph(r);
            toposort();
            for(int i=0;i<m;i++)
            {
                if(a[i].w<=r && top[a[i].u]>top[a[i].v])ans.push_back(i+1);
            }
            int si=ans.size();
            printf("%lld %d
    ",r,si);
            for(int i=0;i<si;i++)
            {
                printf("%d%c",ans[i]," 
    "[i==si-1]);
            }
            
        }
    }
    View Code

    F. Ivan and Burgers

    给出 n 个数,q次区间查询,每次查询,让你选择任意个下标为 [ l , r ] 区间内的任意数,使这些数异或起来最大,输出最大值。

    思路:离线加线性基。

    线性基学习博客1

    线性基学习博客2

    对于此题,先把区间按照 r 从小到大排序,然后依次处理这些区间,每次插入线性基时,优先保留下标比较大的线性基。查询时,只异或上下标大于 l 的值。

    记住异或的符号的优先级很低,所以  if( res^p[i] > res )这样的代码是会wa死的,要注意(这道题这么写,样例都过不了)

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll; 
    const int maxn=5e5+10;
    int a[maxn],q,n,p[30],pos[30],ans[maxn];
    struct node{
        int l,r,id;
        friend bool operator<(const node &a,const node &b)
        {
            return a.r<b.r;
        }
    }op[maxn]; 
    void init(){
        clr(p,0);
    }
    void add(int val,int id){
        for(int i=20;i>=0;i--)
        {
            if(val&(1<<i))
            {
                if(!p[i]){
                    p[i]=val,pos[i]=id;
                    break;
                }
                if(pos[i]<id){
                    swap(pos[i],id),swap(val,p[i]);
                }
                val^=p[i];
            }
        }
    }
    int query(int l)
    {
        int res=0;
        for(int i=20;i>=0;i--)
        {
            if(pos[i]>=l)
            {
                if((res^p[i])>res)
                {
                    res=res^p[i];
                }
            }
        }
        return res;
    }
    int main(){
        while(cin>>n)
        {
            init();
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
            }
            cin>>q;
            for(int i=1;i<=q;i++)
            {
                scanf("%d%d",&op[i].l,&op[i].r);
                op[i].id=i;
            }
            sort(op+1,op+1+q);
            int l=1;
            for(int i=1;i<=q;i++)
            {
                while(l<=op[i].r&&l<=n)
                {
                    add(a[l],l);
                    l++;
                }
                ans[op[i].id]=query(op[i].l);
            }
            for(int i=1;i<=q;i++)
            {
                printf("%d
    ",ans[i]);
            }
        }
    }
    View Code
  • 相关阅读:
    于丹的婚姻观
    相貌与成功的关系—俞敏洪6月2号在同济大学的演讲
    NetBeans IDE 6.9.1 发布
    NetBeans IDE 6.9.1 发布
    NetBeans 时事通讯(刊号 # 112 Aug 05, 2010)
    VS Feature Pack学习之使用CMFCMenuBar自定义菜单栏
    使用 Apache Wink、Eclipse 和 Maven 开发 RESTful Web 服务
    Have to run sudo dhclient eth0 automatically every boot
    java regex
    HTTPCLIENT 解决乱码方案 linfeng_0212的日志 网易博客
  • 原文地址:https://www.cnblogs.com/mountaink/p/10346243.html
Copyright © 2011-2022 走看看