频道栏目
首页 > 程序开发 > 软件开发 > C++ > 正文
HDU 多校第三场
2013-08-01 16:21:04           
收藏   我要投稿

HDU 4628  Pieces

状态压缩dp,dp功底还是太弱了


[cpp] 
#include <cstdio>  
#include <iostream>  
#include <cmath>  
#include <cstring>  
# define N 16  
using namespace std; 
//状态i的二进制中,1表示该位字符存在,0表示不存在  
int dp[1 << N],nice[1 << N]; //dp[i]表示i状态下,删除剩余字符需要的最少步数,nice[i]表示状态i下,他是否是回文  
char str[N]; 
 
void init() { 
    memset(dp,0,sizeof(dp)); 
    memset(nice,0,sizeof(nice)); 

 
int dfs(int n) { 
    if(dp[n] != 0) return dp[n]; 
    int ans = 100; 
    for(int i=n; i>=1; i &= n,i--) {// i & n 则舍去了诸多不能由i转化到n的状态  
 
        if(nice[i] && (i|n) == n) { 
            ans = min(ans,dfs(n-i)+1); 
        } 
    } 
    return dp[n] = ans; 

 
int main() { 
    int T; 
    cin >> T; 
    while(T --) { 
        init(); 
        scanf("%s",str); 
        int len = strlen(str); 
        int n = 1 << len; 
        for(int i=0; i<n; i++) { 
            int cnt = 0; char tmp[N]; 
            for(int j=0; j<len; j++) { 
                if((i>>j) & 1)  {//表示i右移j位,末尾是零还是一  
                    tmp[cnt ++] = str[len-1-j]; 
                } 
            } 
            int l,r,flag = 1; 
            for(l=0,r=cnt-1; l<r; l++,r--) { 
                if(tmp[l] != tmp[r]) { 
                    flag = 0; 
                    break; 
                } 
            } 
            if(flag == 1) { 
 
                nice[i] = 1; 
                dp[i] = 1; 
            } 
        } 
        printf("%d\n",dfs(n-1)); 
    } 
    return 0; 

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
# define N 16
using namespace std;
//状态i的二进制中,1表示该位字符存在,0表示不存在
int dp[1 << N],nice[1 << N]; //dp[i]表示i状态下,删除剩余字符需要的最少步数,nice[i]表示状态i下,他是否是回文
char str[N];

void init() {
    memset(dp,0,sizeof(dp));
    memset(nice,0,sizeof(nice));
}

int dfs(int n) {
    if(dp[n] != 0) return dp[n];
    int ans = 100;
    for(int i=n; i>=1; i &= n,i--) {// i & n 则舍去了诸多不能由i转化到n的状态

        if(nice[i] && (i|n) == n) {
            ans = min(ans,dfs(n-i)+1);
        }
    }
    return dp[n] = ans;
}

int main() {
    int T;
    cin >> T;
    while(T --) {
        init();
        scanf("%s",str);
        int len = strlen(str);
        int n = 1 << len;
        for(int i=0; i<n; i++) {
            int cnt = 0; char tmp[N];
            for(int j=0; j<len; j++) {
                if((i>>j) & 1)  {//表示i右移j位,末尾是零还是一
                    tmp[cnt ++] = str[len-1-j];
                }
            }
            int l,r,flag = 1;
            for(l=0,r=cnt-1; l<r; l++,r--) {
                if(tmp[l] != tmp[r]) {
                    flag = 0;
                    break;
                }
            }
            if(flag == 1) {

                nice[i] = 1;
                dp[i] = 1;
            }
        }
        printf("%d\n",dfs(n-1));
    }
    return 0;
}

 

HDU 4630 No Pain No Game

思路: 考虑从左到右扫描,对于每个数,记录在它之前出现,并且最靠右边的那个它的倍数,用previ表示。考虑当前数i的所有约数x,对于所有r >= i,l <= previ 的询问,x就是可能的答案了。

用树状数组或者线段树维护(此题线段树速度巨慢)因为n只有5W,可以预处理好倍数约数关系

 

 

[cpp] 
#include <cstdio>  
#include <iostream>  
#include <cmath>  
#include <algorithm>  
#include <vector>  
#include <cstring>  
# define MAX 51111  
# define ll(x) x << 1  
# define rr(x) x << 1 | 1  
using namespace std; 
 
inline void RD(int &ret) { 
    char c; 
    do { 
        c = getchar(); 
    } while(c < '0' || c > '9') ; 
    ret = c - '0'; 
    while((c=getchar()) >= '0' && c <= '9') 
        ret = ret * 10 + ( c - '0' ); 

 
inline void OT(int a){ 
    if(a >= 10)OT(a / 10) ; 
    putchar(a % 10 + '0') ; 

int a[MAX],pos[MAX],print[MAX]; 
struct node { 
    int l,r; 
    int num; 
}ask[MAX]; 
 
struct Node { 
    int s,e,next; 
}v[1111111]; 
int head[MAX]; 
int n,q,num = 0; 
 
void addedge(int s,int e) { 
    v[num].s = s; 
    v[num].e = e; 
    v[num].next = head[s]; 
    head[s] = num++; 

 
void init() { //预处理  
    memset(head,-1,sizeof(head)); 
    for(int i=1; i<=50000; i++) { 
        for(int j=i; j<=50000; j+=i) { 
           addedge(j,i); 
        } 
    } 

 
bool cmp(node a,node b) { 
    return a.r < b.r; 

 
struct Tree { 
    int l,r,maxx,add,mid; 
}tree[MAX*4]; 
 
void up(int x) { 
    tree[x].maxx = max(tree[ll(x)].maxx,tree[rr(x)].maxx); 

 
void down(int x) { 
    if(tree[x].add != 0) { 
        tree[ll(x)].add = max(tree[x].add,tree[ll(x)].add); 
        tree[rr(x)].add = max(tree[x].add,tree[rr(x)].add); 
        tree[ll(x)].maxx = max(tree[x].add,tree[ll(x)].maxx); 
        tree[rr(x)].maxx = max(tree[x].add,tree[rr(x)].maxx); 
        tree[x].add = 0; 
    } 

 
void build(int l,int r,int x) { 
    tree[x].l = l; 
    tree[x].r = r; 
    tree[x].mid = (l+r) >> 1; 
    tree[x].maxx = 0; 
    tree[x].add = 0; 
    if(l == r) return ; 
    build(l,tree[x].mid,ll(x)); 
    build(tree[x].mid+1,r,rr(x)); 

 
void update(int l,int r,int x,int t) { 
    if(l <= tree[x].l && r >= tree[x].r) { 
        tree[x].add = max(t,tree[x].add); 
        tree[x].maxx = max(tree[x].maxx,tree[x].add); 
        return ; 
    } 
    down(x); 
    if(r <= tree[x].mid) update(l,r,ll(x),t); 
    else if(l > tree[x].mid) update(l,r,rr(x),t); 
    else { 
        update(l,tree[x].mid,ll(x),t); 
        update(tree[x].mid+1,r,rr(x),t); 
    } 
    up(x); 

 
int query(int l,int x) { 
    if(tree[x].l == tree[x].r) { 
        return tree[x].maxx; 
    } 
    down(x); 
    if(l > tree[x].mid) return query(l,rr(x)); 
    else return query(l,ll(x)); 

int main() { 
    int T; 
    cin >> T; 
    init(); 
    while( T--) { 
        RD(n); 
        build(1,n,1); 
        memset(pos,0,sizeof(pos)); 
        for(int i=1; i<=n; i++) RD(a[i]); 
        RD(q); 
        for(int i=1; i<=q; i++) { 
            RD(ask[i].l); 
            RD(ask[i].r); 
            ask[i].num = i; 
        } 
        sort(ask+1,ask+1+q,cmp); 
        int cnt = 1,flag = 0; 
        for(int i=1; i<=n; i++) { 
            for(int j=head[a[i]]; j != -1; j = v[j].next) { 
                int t = v[j].e; 
                if(pos[t] != 0) update(1,pos[t],1,t); 
                pos[t] = i; 
            } 
            while(ask[cnt].r <= i) { 
               print[ask[cnt].num] = query(ask[cnt].l,1); 
                cnt++; 
                 if(cnt > q) { 
                    flag = 1; 
                    break; 
                 } 
            } 
            if(flag) break; 
        } 
        for(int i=1; i<=q; i++) OT(print[i]),puts(""); 
    } 
    return 0; 

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstring>
# define MAX 51111
# define ll(x) x << 1
# define rr(x) x << 1 | 1
using namespace std;

inline void RD(int &ret) {
    char c;
    do {
        c = getchar();
    } while(c < '0' || c > '9') ;
    ret = c - '0';
    while((c=getchar()) >= '0' && c <= '9')
        ret = ret * 10 + ( c - '0' );
}

inline void OT(int a){
    if(a >= 10)OT(a / 10) ;
    putchar(a % 10 + '0') ;
}
int a[MAX],pos[MAX],print[MAX];
struct node {
    int l,r;
    int num;
}ask[MAX];

struct Node {
    int s,e,next;
}v[1111111];
int head[MAX];
int n,q,num = 0;

void addedge(int s,int e) {
    v[num].s = s;
    v[num].e = e;
    v[num].next = head[s];
    head[s] = num++;
}

void init() { //预处理
    memset(head,-1,sizeof(head));
    for(int i=1; i<=50000; i++) {
        for(int j=i; j<=50000; j+=i) {
           addedge(j,i);
        }
    }
}

bool cmp(node a,node b) {
    return a.r < b.r;
}

struct Tree {
    int l,r,maxx,add,mid;
}tree[MAX*4];

void up(int x) {
    tree[x].maxx = max(tree[ll(x)].maxx,tree[rr(x)].maxx);
}

void down(int x) {
    if(tree[x].add != 0) {
        tree[ll(x)].add = max(tree[x].add,tree[ll(x)].add);
        tree[rr(x)].add = max(tree[x].add,tree[rr(x)].add);
        tree[ll(x)].maxx = max(tree[x].add,tree[ll(x)].maxx);
        tree[rr(x)].maxx = max(tree[x].add,tree[rr(x)].maxx);
        tree[x].add = 0;
    }
}

void build(int l,int r,int x) {
    tree[x].l = l;
    tree[x].r = r;
    tree[x].mid = (l+r) >> 1;
    tree[x].maxx = 0;
    tree[x].add = 0;
    if(l == r) return ;
    build(l,tree[x].mid,ll(x));
    build(tree[x].mid+1,r,rr(x));
}

void update(int l,int r,int x,int t) {
    if(l <= tree[x].l && r >= tree[x].r) {
        tree[x].add = max(t,tree[x].add);
        tree[x].maxx = max(tree[x].maxx,tree[x].add);
        return ;
    }
    down(x);
    if(r <= tree[x].mid) update(l,r,ll(x),t);
    else if(l > tree[x].mid) update(l,r,rr(x),t);
    else {
        update(l,tree[x].mid,ll(x),t);
        update(tree[x].mid+1,r,rr(x),t);
    }
    up(x);
}

int query(int l,int x) {
    if(tree[x].l == tree[x].r) {
        return tree[x].maxx;
    }
    down(x);
    if(l > tree[x].mid) return query(l,rr(x));
    else return query(l,ll(x));
}
int main() {
    int T;
    cin >> T;
    init();
    while( T--) {
        RD(n);
        build(1,n,1);
        memset(pos,0,sizeof(pos));
        for(int i=1; i<=n; i++) RD(a[i]);
        RD(q);
        for(int i=1; i<=q; i++) {
            RD(ask[i].l);
            RD(ask[i].r);
            ask[i].num = i;
        }
        sort(ask+1,ask+1+q,cmp);
        int cnt = 1,flag = 0;
        for(int i=1; i<=n; i++) {
            for(int j=head[a[i]]; j != -1; j = v[j].next) {
                int t = v[j].e;
                if(pos[t] != 0) update(1,pos[t],1,t);
                pos[t] = i;
            }
            while(ask[cnt].r <= i) {
               print[ask[cnt].num] = query(ask[cnt].l,1);
                cnt++;
                 if(cnt > q) {
                    flag = 1;
                    break;
                 }
            }
            if(flag) break;
        }
        for(int i=1; i<=q; i++) OT(print[i]),puts("");
    }
    return 0;
}

 

点击复制链接 与好友分享!回本站首页
相关TAG标签 第三
上一篇:花非花--记vs2010 c++调试问题
下一篇:HDU 2051 Bitset
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站