学习笔记(6)

  这两天做的CF,突然发现数学知识真的是不够用了,别人一下想出来的东西,我想了半天,又是查题解,又是问TG的,最后才明白,还是太弱了啊,贴下我纠结好久的题,算是数学题吧...

Hacking Cypher

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<string>
#include<set>
#include<algorithm>
#include<cmath>


#define ll __int64
#define MAX 1000009
using namespace std;


int vis[MAX];


int main()
{
    string b,xx,yy;
    ll x,y,i;
    cin>>b;
    cin>>x>>y;
    int flag = 0;
    int len = b.size();
    int k = 0;
    for(i=0; i<len; i++)
    {
        k = k*10+b[i]-'0';
        if(k%x==0)
        {
            vis[i+1]++;
        }
        k%=x;
    }
    int l =1;
    int t = 0;
    for(i=len-1; i>=0; i--)
    {
        t = l*(b[i]-'0')%y+t%y;
        if(t%y==0)
        {
            vis[i]++;
        }
        l = (l*10)%y;
    }
    for(int i=0; i<len; i++)
        if(vis[i]==2 && b[i]-48!=0)
        {
            printf("YES\n");
            for(int j=0; j<i; j++)
                printf("%c",(int)b[j]);
            printf("\n");
            for(int j=i; j<len; j++)
                printf("%c",b[j]);
            printf("\n");
            return 0;
        }
    printf("NO\n");


}
/*
思路:从左到右求出在每一位对x的余数求出之后 在判断余数是否对x取余是否为零,如果为零,标记位置;
      从右到左求出在每一位对y的余数求出之后 在判断余数是否对y取余是否为零,如果为零,标记位置;
      如果vis[i]==2&&b[i]-'0'!=0,输出答案
*/

==

就是这么弱,TG都AK的题····我才A了三个,还有两个是赛后A的,唉,还要好好学啊,今天接着学习线段树,应该是单点更新的最后一题了,说道线段树,昨天求了最小逆序数,当然了,是照傻崽敲得...

#include<cstdio>
#include<algorithm>

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
 using namespace std; const int MAXN = 55555; int sum[MAXN<<2]; void PushUP(int rt) {
    sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(int l,int r,int rt) {
    sum[rt] = 0; if(l == r ) { return ; } int m =(r+l)>>1;
    build(lson);
    build(rson);
    PushUP(rt); } void update(int p,int l,int r,int rt) { if(l == r) {
        sum[rt]++; return ; } int m = (r+l)>>1; if(p<=m)
        update(p,lson); else
        update(p,rson);
    PushUP(rt); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return sum[rt]; } int m =(l+r)>>1; int ret = 0; if(L<=m)
        ret+=query(L,R,lson); if(R>m)
        ret+=query(L,R,rson); return ret; } int x[MAXN]; int main() { int n,sum,i; while(~scanf("%d",&n)) {
        build(0,n-1,1);
        sum = 0; for(i=0;i<n;i++) {
            scanf("%d",&x[i]);
            sum += query(x[i],n-1,0,n-1,1);
            update(x[i],0,n-1,1); } int ret = sum; for(i = 0;i<n;i++) {
            sum+=n-2*x[i]-1;
            ret = min(sum,ret); }
        printf("%d\n",ret); } }
这里有两点说明,逆序数的比较大小实际上就是存储顺序,先存入的自加1,然后区间求和,这个和,也就是逆序对的个数,还有个规律,就是每当第一个数放到最后是,逆序数减少a[i]个,增加n-a[i]-1个



你可能感兴趣的:(学习笔记(6))