平时十测

题解:

第一题:大模拟,横躺竖躺站立三种状态,对每种状态分别模拟就好了;

我记录每面旋转后对应原来的面,很明显麻烦了,我大模拟写了2个小时,别人40分钟A,DS能力太差了;

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

const int M = 2005;
char opt[105];
int vis[M][M], mx;
int zz[8];

int zl[5][2] = {{0,0},{1,0},{-1,0},{0,1},{0,-1}}, a[2];
inline int get(char c){
    switch(c){
        case 'E':return 1;
        case 'W':return 2;
        case 'N':return 3;
        case 'S':return 4;
    }
}
int ff[8], p[8];
int sta[7][8] = {
{0, 1, 2, 6, 5, 3, 4},
{0, 5, 2, 6, 4, 3, 1},//E
{0, 6, 2, 5, 4, 1, 3},//W
{0, 2, 3, 4, 1, 5, 6},//N
{0, 4, 1, 2, 3, 5, 6}//S
};
void init(){
    memset(vis, 0, sizeof(vis));
    mx = 0;
    for(int i=1;i<=6;i++)zz[i]=sta[0][i];
}
inline void work(int t){
    for(int i=1;i<=6;i++)ff[i]=zz[i];
    for(int i=1;i<=6;i++)zz[i]=ff[sta[t][i]];
}

int main(){
    freopen("block.in","r",stdin);
    freopen("block.out","w",stdout);
    int T, h;
    scanf("%d", &T);
    p[1] = p[6]= 1;
    while(T--){
        init();
        scanf("%d", &h);
        for(int i=2;i<=5;i++)p[i]=h;
        scanf("%s", &opt);
        int st = 1000, ed = 1000, ss = 1000, dd = 1000;
        vis[st][ed]++;
        int len = strlen(opt);
        for(int i = 0; i < len; i++){
            int t = get(opt[i]);
            
            int dx = zl[t][0], dy = zl[t][1], nx, ny, now;
            if(dx){
                if(p[zz[6]]==1&&p[zz[1]]==h)now=1;
                else if(p[zz[6]]==p[zz[1]]&&p[zz[1]]==h)now=1;
                else now=h;
                if(dx > 0){
                    
                    nx = ss + dx * now;
                    for(int k=ed;k<=dd;k++)
                    for(int j=ss+1;j<=nx;j++)if( (++vis[j][k])>mx ) mx = vis[j][k];    
                } 
                if(dx < 0) {
                    nx = st + dx * now;
                    for(int k=ed;k<=dd;k++)
                    for(int j=st-1;j>=nx;j--)if( (++vis[j][k])>mx ) mx = vis[j][k];    
                }
                
            }
            else{
                if(p[zz[6]]==1&&p[zz[1]]==h)now=1;
                else if(p[zz[6]]==p[zz[1]]&&p[zz[1]]==h)now=1;
                else now=h;
                
                
                if(dy > 0){
                    
                    ny = dd + dy * now;
                    for(int k=st;k<=ss;k++)
                    for(int j=dd+1;j<=ny;j++)if( (++vis[k][j])>mx ) mx = vis[k][j];    
                } 
                
                if(dy < 0) {
            
                    ny = ed + dy *now;
                    for(int k=st;k<=ss;k++)
                    for(int j=ed-1;j>=ny;j--)if( (++vis[k][j])>mx ) mx = vis[k][j];
                }
                
            }
            if(dx){
                if(dx > 0) {
                    st=ss+1;ss=nx; 
                    //if(ss==st)
                }
                else {
                    ss=st-1;st=nx;
                }
            }
            else{
                if(dy > 0){
                    ed=dd+1;dd=ny;
                }
                else {
                    dd=ed-1;ed=ny;
                }
            }
            //printf("%d:%c %d %d %d %d    %d %d %d %d %d\n",i, opt[i],st,ss,ed,dd,dx,dy,now,nx,ny);
            work(t);
            //for(int i=1;i<=6;i++)printf("%d ",zz[i]);puts("");
        }
        int sx=max(ss-st+1, dd-ed+1);
        if(ss==st)
            for(int i=1;i<=sx;i++)printf("%d ", ss-1000);
        else for(int i=st;i<=ss;i++)printf("%d ", i-1000);
        puts("");
        if(ed==dd)for(int i=1;i<=sx;i++)printf("%d ",dd-1000);
        else for(int i=ed;i<=dd;i++)printf("%d ", i-1000);
        puts("");
        printf("%d\n",mx);    
        
    }
    
}
View Code

 

第二题:前面O(N)50%的分,后面就不会了;

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define RG register
ll bin[20];
const int M = 1e7+2;
int bit[M][4];

inline void cut(ll &num){
    while(num%10 == 0)num/=10;
    num%=bin[9];
}

void init(){
    ll now = 1;
    bin[0] = 1;
    for(int i = 1; i <= 17; i++) bin[i]=bin[i-1]*10;
    for(RG ll i = 1; i <= 1e7; i++){
        now*=i;
        cut(now);
        for(int j = 1; j <= 3; j++){
            bit[i][j] = now%bin[j];     
        }
    //    printf("%lld %d\n", i, bit[i][3]);
    }
        
}
void print(int k, int num){
    if(k == 3)printf("%03d\n",num);
    if(k == 2)printf("%02d\n",num);
    if(k == 1)printf("%d\n",num);
}


int main(){
    freopen("num.in","r",stdin);
    freopen("num.out","w",stdout);
    int T;
    scanf("%d", &T);
    //int tt=clock();
    init();
    while(T--){
        int n, k;
        scanf("%d%d", &n, &k);
        print(k, bit[n][k]);
    }
    //int cc=clock();
    ////fprintf(stderr,"FUCK %d",cc-tt);
    
}
View Code

 

第三题:对于每个节点答案组成必须是1234……k,才合法,我们可以每次在节点后面添加id,最后判断组成串是否合法即可,这就相当于一个哈希,变成了经典的线段树操作,区间乘一个数加一个数

#include<bits/stdc++.h>
using namespace std;
const int M = 200005;
#define ll unsigned long long
const ll bas = 2333;
int n, k, cnt;
ll stan;

struct Node{
    Node *ls, *rs;
    ll A, B;
    void down(){
        if(A == 1 && !B)return ;
        ls->B = ls->B*A + B;
        ls->A *= A;
        rs->B = rs->B*A + B;
        rs->A *= A;
        A = 1, B = 0;
    }
}pool[M<<2], *root,*tail=pool; 
Node *build(int lf=1,int rg=n){
    Node *nd =++tail;
    nd->A = 1, nd->B = 0;
    if(lf==rg);
    else {
        int mid=(lf+rg)>>1;
        nd->ls=build(lf,mid);
        nd->rs=build(mid+1,rg);
    }
    return nd;
}
#define Ls lf,mid,nd->ls
#define Rs mid+1,rg,nd->rs
void modify(int L, int R, int dv, int lf=1,int rg=n,Node *nd = root){
    if(L <=lf && rg <= R){
        nd->A *= bas;
        nd->B = nd->B * bas + dv;
    }
    else {
        int mid=(lf+rg)>>1;
        nd->down();
        if(L<=mid)modify(L, R, dv, Ls);
        if(R>mid)modify(L, R, dv, Rs);
    }
}
void getdown(int lf=1,int rg=n,Node *nd=root){
    if(lf==rg){
        if(nd->B == stan) cnt++;
    }
    else {
        int mid=(lf+rg)>>1;
        nd->down();
        getdown(Ls);
        getdown(Rs);
    }
}

int main(){
    freopen("deco.in","r",stdin);
    freopen("deco.out","w",stdout);
    int T;
    scanf("%d%d%d", &n,&k,&T);
    root=build();
    int l,r,id;
    for(int i=1;i<=T;i++){
        scanf("%d%d%d",&l,&r,&id);
        modify(l,r,id);
    }
    stan = 0;
    for(int i = 1; i <= k; i++)
        stan = stan * bas + i;
    getdown();
    printf("%d\n",cnt);
}
View Code

 

posted @ 2018-10-06 18:20  Ed_Sheeran  阅读(199)  评论(0编辑  收藏  举报