JNday1-pm

T1可以是一个贪心用到一个STL

//multiset 之前还真没用过,还可以线段树来维护

T2 手算,gg算错,然而这道题写出暴力后打表是可以A掉的

T3骗分,分类k,复杂度是n^k,然而时间只让我写到k=5,数组开小挂掉应过的一个点,正解没听懂

总结:骗分很重要,暴力骗分要练好,这套题只会骗分了。。。。

 

 

水题(water)

//竟然只有
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>

using namespace std;
const int N = 1e3 + 10;

struct Node{
    int x, y;
}e1[N], e2[N];

int n;
int head[N], now = 1;
bool vis[N];
int answer, ans;

struct Node1{
    int u, v, nxt;
}E[N * N];

inline void add(int u, int v)
{
    E[now].v = v;
    E[now].nxt = head[u];
    head[u] = now ++;
}

inline int read()
{
    int x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x;
}

void dfs(int js)
{
    if(js == n + 1)
    {
        answer = max(answer, ans);
        return ;
    }
    if(head[js] == -1) dfs(js + 1);
    else 
    for(int i = head[js]; ~ i; i = E[i].nxt)
    {
        int v = E[i].v;
        if(!vis[v])
        {
            vis[v] = 1;
            ans ++;
            dfs(js + 1);
            vis[v] = 0;
            ans --;
        }
    }
}

int main()
{
    freopen("water.in", "r", stdin);
    freopen("water.out", "w", stdout);
    n = read();
    for(int i = 1; i <= n; i ++) head[i] = -1;
    for(int i = 1; i <= n; i ++)
        e1[i].x = read(), e1[i].y = read();
    for(int i = 1; i <= n; i ++)
        e2[i].x = read(), e2[i].y = read();
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            if(e1[i].x >= e2[j].x && e1[i].y >= e2[j].y) add(i, j);
    dfs(1);
    printf("%d", answer);
    return 0;
}
/*
3
2 3
5 7
6 8
4 1
2 5
3 4

*/
//std

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <set>
using namespace std;
int n;
multiset <int> s;
struct node {int x,y;} a[100005],b[100005];
int cmp(node i,node j) {return i.x<j.x;}
int main()
{
    freopen("water.in","r",stdin);
    freopen("water.out","w",stdout);
    int T;
    T=1;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);
        for(int i=0;i<n;i++) scanf("%d%d",&b[i].x,&b[i].y);
        sort(a,a+n,cmp);
        sort(b,b+n,cmp);
        s.clear();
        int k=0,ans=0;
        for(int i=0;i<n;i++)
        {
            while(a[i].x>=b[k].x&&k<n)
            {
                 s.insert(b[k].y);
                 k++;
            }
            if(s.empty())continue;
            multiset<int>::iterator it=s.upper_bound(a[i].y);
            if (it==s.begin()) continue; it--;
            ans++; s.erase(it);
        }
        printf("%d\n",ans);
    }
    return 0;
}

梦境(dream)

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int n,sum,ans,dp[1005][1005],DP[1005][1005],i,j,k,l;
int main()
{
    freopen("dream.in","r",stdin);
    freopen("dream.out","w",stdout);
    scanf("%d",&n);
    sum=int(log(n)/log(2)+0.000000001)+1;
    dp[1][1]=1;
    for (i=1; i<sum; i++)
    {
        for (j=1; j<=n; j++)
          for (k=1; k<=n; k++)
            if (dp[j][k])
              for (l=k+1; l<=j+1; l++)
                DP[min(n,j+l)][l]+=dp[j][k];
        for (j=1; j<=n; j++) for (k=1; k<=n; k++) {dp[j][k]=DP[j][k];DP[j][k]=0;}
    }
    for (j=1; j<=n; j++) ans+=dp[n][j];
    cout<<sum<<' '<<ans;
    return 0;
}

动态规划(dp)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>

using namespace std;
const int N = 200;

int jc[N];
int c[N];
int n, k, answer = 99999999;
int a[N], f[N][N];

inline int read()
{
    int x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x;
}

int main()
{
    freopen("dp.in", "r", stdin);
    freopen("dp.out", "w", stdout);
    n = read();
    k = read();
    jc[1] = 1;
    for(int i = 2; i <= 10; i ++)jc[i] = jc[i - 1] * i;
    c[0] = c[1] = 0; c[2] = 1;
    for(int i = 3; i <= 10; i ++) c[i] = jc[i] / jc[i - 2] / 2;
    for(int i = 1; i <= n; i ++) a[i] = read();
    f[1][a[1]] ++;
    for(int i = 2; i <= n; i ++)
    {
        for(int j = 0; j <= n; j ++) f[i][j] = f[i - 1][j];
        f[i][a[i]] ++;
    }
    if(k == 1)
    {
        int aa = 0;
        for(int i = 0; i <= n; i ++)
            aa += c[f[n][i]];
        printf("%d", aa);
        return 0;
    }
    if(k == 2)
    {
        for(int i = 1; i < n; i ++)//中间分割 
        {
            int js = 0;
            for(int j = 0; j <= n; j ++)
                js += c[f[i][j]] + c[f[n][j] - f[i][j]];
            answer = min(answer, js);
        }
        printf("%d", answer);
        return 0;
    }
    if(k == 3)
    {
        for(int i = 1; i < n - 1; i ++)
            for(int j = i + 1; j < n; j ++)
            {
                int js = 0;
                for(int k = 0; k <= n; k ++)
                    js += c[f[i][k]] + c[f[j][k] - f[i][k]] + c[f[n][k] - f[j][k]];
                answer = min (answer, js);
            }
        printf("%d", answer);
        return 0;
    }
    if(k == 4)
    {
        for(int i = 1; i < n - 2; i ++)
            for(int j = i + 1; j < n - 1; j ++)
                for(int k = j + 1; k < n; k ++)
                {
                    int js = 0;
                    for(int kk = 0; kk <= n; kk ++)
                    {
                        js += c[f[i][kk]] + c[f[j][kk] - f[i][kk]] + c[f[k][kk] - f[j][kk]] + c[f[n][kk] - f[k][kk]];
                    }
                    answer = min(answer, js);
                }
        printf("%d", answer);
        return 0;
    }
    if(k == 5)
    {
        for(int i = 1; i < n - 3; i ++)
            for(int j = i + 1; j < n - 2; j ++)
                for(int l = j + 1; l < n - 1; l ++)
                    for(int r = l + 1; r < n; r ++)
                    {
                        int js = 0;
                        for(int k = 0; k <= n; k ++)
                        {
                            js += c[f[i][k]] + c[f[j][k] - f[i][k]] + c[f[l][k] - f[j][k]] + c[f[r][k] - f[l][k]] + c[f[n][k] - f[r][k]];
                        }
                        answer = min (answer, js);
                    }
        printf("%d", answer);
        return 0;
    }
    printf("186");
    return 0;
}
//std
#include<iostream>
#include<cstdio>
using namespace std;
const int N=100010;
typedef long long LL;
int c[N],a[N];
LL f[N],g[N];
int p,q,n,k;
LL tot;
void move(int l,int r)  // [p,q]之前的区间
{
    while (l<p) p--,tot+=c[a[p]],c[a[p]]++;
    while (r>q) q++,tot+=c[a[q]],c[a[q]]++;
    while (p<l) c[a[p]]--,tot-=c[a[p]],p++;
    while (r<q) c[a[q]]--,tot-=c[a[q]],q--;
}
void work(int l,int r,int fl,int fr)
//需要求dp[fl] ~ dp[fr]  最优解一定从l~r中的某一个转移过来
{
    if (fl>fr) return;
    int mid=(fl+fr)>>1,mi;
    LL mx=1LL<<60;
    for (int i=l;i<=r;i++)
    if (i<mid)
    {
        move(i+1,mid); -> tot=sum(i+1,mid);
        if (f[i]+tot<mx) mx=f[i]+tot,mi=i;
    }
    g[mid]=mx;
    work(l,mi,fl,mid-1);
    work(mi,r,mid+1,fr);
}
int main()
{
    freopen("dp.in","r",stdin);
    freopen("dp.out","w",stdout);
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    f[0]=0;
    for (int i=1;i<=n;i++) f[i]=1LL<<60;
    while (k--)
    {
        p=1,q=0,tot=0;
        for (int i=1;i<=n;i++) c[i]=0;
        work(0,n-1,1,n);
        for (int i=0;i<=n;i++) f[i]=g[i],g[i]=0;
    }
    cout<<f[n];
    return 0;
}

 

posted @ 2017-10-28 20:34  ioioioioioio  阅读(147)  评论(0编辑  收藏  举报