Codeforces Round #348 (VK Cup 2016 Round 2, Div. 1 Edition)

A. Little Artem and Matrix

  没什么好说的,逆向模拟一下。

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;

#define ll long long

int a[10010][5];

int ans[111][111];

int main(){
    int n,m,q;
    cin>>n>>m>>q;

    for(int i=1;i<=q;i++){
        scanf("%d",&a[i][0]);
        if(a[i][0]==3){
            for(int j=1;j<=3;j++){
                scanf("%d",&a[i][j]);
            }
        }else{
            scanf("%d",&a[i][1]);

        }
    }

    for(int i=q;i>0;i--){
        if(a[i][0]==1){ 
            int tmp = ans[ a[i][1] ][m];
            for(int j=m;j>1;j--){
                ans[ a[i][1] ][j] = ans[ a[i][1] ][j-1];
            }
            ans[ a[i][1] ][1] = tmp;
        }else if(a[i][0]==2){
            int tmp = ans[ n ][a[i][1]];
            for(int j=n;j>1;j--){
                ans[ j ][a[i][1]] = ans[j-1][ a[i][1] ];
            }
            ans[1][ a[i][1] ] = tmp;
        }else if(a[i][0]==3){
            ans[a[i][1]][a[i][2]] = a[i][3];
        }
    }

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cout<<ans[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

B. Little Artem and Dance

  其实分析一下就能发现,奇数的相对位置是不会变的,偶数的也是。所以一个简单的做法就是维护1和2的位置。

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;

#define ll long long

int ans[1000010];

int main(){
    int n,q;
    cin>>n>>q;

    int one = 1;
    int two = 2;

    for(int i=1;i<=q;i++){
        int op;
        scanf("%d",&op);
        if(op==1){
            int x;
            scanf("%d",&x);
            one+=x;
            two+=x;
        }else{
            if(one&1){
                one++;
            }else{
                one--;
            }
            if(two&1){
                two++;
            }else{
                two--;
            }
        }
        while(one>n){
            one-=n;
        }
        while(one<1){
            one+=n;
        }
        while(two>n){
            two-=n;
        }
        while(two<1){
            two+=n;
        }
    }

    for(int i=1;i<=n;i+=2){
        ans[one]=i;
        one+=2;
        if(one>n){
            one-=n;
        }
    }

    for(int i=2;i<=n;i+=2){
        ans[two]=i;
        two+=2;
        if(two>n){
            two-=n;
        }
    }

    for(int i=1;i<=n;i++){
        printf("%d ",ans[i]);
    }

    return 0;
}

C. Little Artem and Random Variable

  大坑!C居然比D难,差一点码完,巨亏。。
  我们按顺序推两个骰子的每个点的概率即可。根据max和min的分布,可以推出一个一元二次方程,化简然后解之可以得到每个点的概率。。
  这个题我跪了一发,跪在二次方程判别式出现了一个极小的负数。。

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;

#define ll long long


double ansA[100010];
double ansB[100010];


double delta;
double x1,x2;

// ax^2 + bx + c = 0
void solve(double a,double b,double c){
    double d=b*b-4*a*c; 
    delta = d;

    if(d<=0){ 
        x1=x2=(-b)/(2*a); 
    }else{
        double e=sqrt(d); 
        x1=(-b+e)/(2*a); 
        x2=(-b-e)/(2*a); 
    } 
}

double MIN[100010];
double MAX[100010];

int main(){
    int n;
    cin>>n;

    for(int i=1;i<=n;i++){
        scanf("%lf",&MAX[i]);
    }

    for(int i=1;i<=n;i++){
        scanf("%lf",&MIN[i]);
    }

    double suma=0;
    double sumb=0;
    for(int i=1;i<=n;i++){
        // ansA[i] + ansB[i] = MIN[i] + MAX[i]
        // sumb*ansA[i] +suma*ansB[i] + ansA[i]*ansB[i] = MAX[i]
        // 
        double minSum = min(suma,sumb);
        // let x = ansA[i]

        double sum = MIN[i] + MAX[i];

        double a = -1.0;
        double b = sumb - suma + sum;
        double c = suma*sum - MAX[i] ;

        solve(a,b,c);

        x2 = sum-x1;
        ansA[i] = x1;
        ansB[i] = x2;

        suma += x1;
        sumb += x2;
    }

    for(int i=1;i<=n;i++){
        cout<<ansA[i]<<" ";
    }
    cout<<endl;
    for(int i=1;i<=n;i++){
        cout<<ansB[i]<<" ";
    }

    return 0;
}

D. Little Artem and Time Machine

  又是喜闻乐见的数据结构题。。这个题并不需要什么高端的姿势,大家常见的数据结构就能解决。首先,对不同的数的操作其实是独立的,可以分开处理。对于每个操作数,把操作时间离散化,用BIT维护对它进行增加,删除的时间,再根据查询操作的时间点查询一下在这之前被增加/删除了多少次,增加次数减去删除次数就是答案。。

#include <bits/stdc++.h>

using namespace std;

struct operation{
    int op;
    int time;
    int x;
    int id;
    bool operator<(const operation &other)const{
        if(x!=other.x){
            return x<other.x;
        }
        return id<other.id;
    }
}ops[100010];

int ca[100010];
int cr[100010];

int lowbit(int x){
    return x&(-x);
}

int sz;
void updatea(int x){
    while(x<=sz){
        ca[x]++;
        x+=lowbit(x);
    }
}

int querya(int x){
    int res = 0;
    while(x){
        res+=ca[x];
        x-=lowbit(x);
    }
    return res;
}

void updater(int x){
    while(x<=sz){
        cr[x]++;
        x+=lowbit(x);
    }
}

int queryr(int x){
    int res = 0;
    while(x){
        res+=cr[x];
        x-=lowbit(x);
    }
    return res;
}

int res[100010];

int main(){
    memset(res,-1,sizeof(res));
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        scanf("%d%d%d",&ops[i].op,&ops[i].time,&ops[i].x);
        ops[i].id = i;
    }
    sort(ops,ops+n);

    for(int i=0;i<n;i++){
        int end = i;
        while(ops[end].x==ops[end+1].x && end<n-1){
            end++;  
        }

        map<int,int> mp;
        for(int j=i;j<=end;j++){
            mp[ops[j].time];
        }

        int k = 1;

        for(auto it = mp.begin();it!=mp.end();it++){
            it->second = k++;
        }

        sz = end-i+2;
        for(int j=0;j<=sz;j++){
            ca[j] = cr[j] = 0;
        }
        for(int j=i;j<=end;j++){
            int mpTime = mp[ops[j].time];
            if(ops[j].op==1){
                updatea(mpTime);
            }else if(ops[j].op==2){
                updater(mpTime);
            }else{
                int ans = querya(mpTime) - queryr(mpTime);
                res[ops[j].id] = ans;
            }
        }
        i = end;
    }


    for(int i=0;i<n;i++){
        if(res[i]!=-1){
            printf("%d\n",res[i]);
        }
    }
    return 0;
}

你可能感兴趣的:(codeforces)