2012长春网络赛

记得这场比赛3题出线,是我打的第一次regional,悲剧只出1题,RP掉光。

Alice and Bob

 这题是矩形覆盖矩形的问题,看懂题目后就应该反映过来,此题类似LIS。

n=10w,N^2的LIS显然不行,需要NlogN的方程。

要转化为1维的LIS,此题就必须先对给定的矩形按x排序,然后再转化为y上的LIS。算是一个二次排序吧,题目和2009的waterloo某题超像,只是当时不知道。。

注意矩形是二维的,要分清何时更新LIS的答案数组。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <set>
using namespace std;
#define NN 101000
struct ret{
    int h,w,pre;
    bool isok(const ret &b){
        if (h>b.h || ( h==b.h && w>=b.w) )
            return true;
        else return false;
    }
    bool operator < (const ret & b){
        if (h<b.h || ( h==b.h && w<b.w) )
            return true;
        else return false;
    }
};
ret a[NN],b[NN];
inline bool cmp(const ret&a, const ret&b){
    if (a.h<b.h || ( a.h==b.h && a.w<b.w) )
        return true;
    else return false;
}
int main(){
    int T,i,j,k,n,sum,bl,br,bmid;
    scanf("%d",&T);
    multiset<int> s;
    multiset<int>::iterator it;
    while (T--){
        sum=0;
        s.clear();
        scanf("%d",&n);
        for (i=0;i<n;i++)
            scanf("%d %d",&a[i].h,&a[i].w);
        for (i=0;i<n;i++)
            scanf("%d %d",&b[i].h,&b[i].w);
        sort(a,a+n,cmp);
        sort(b,b+n,cmp);
        for (i=0,j=0; i<n; i++){
            while (j<n && b[j].h<=a[i].h){
                s.insert(b[j].w);
                j++;
            }
            if (s.empty()) continue;
            it=s.upper_bound(a[i].w);
            if (it==s.begin()) continue;
            it--;
            s.erase(it),sum++;

        }
        printf("%d\n",sum);

    }

    return 0;
}

A Simple Problem with Integers

哈哈,模板题有木有。

突破口在k<=10。开55个树状数组,记录所有数mod k的可能,然后就变成了区间和问题了。求和的时候再从k=1->10的和加起来,就OK了。

注意分组的时候用/k 不要得到0这个起点,或者你的BIT单独考虑了0这个点。

还有超内存的情况⊙﹏⊙,还是初始化的使用new一下吧,静态分配内存似乎要到32M,但是k越大,n/k越小,new一下慢不了多少,内存才6m。

 

#include <stdio.h>
#include <string.h>
#define N 50005

#define lowbit(i) ( i & (-i) )
//#define _clr(x) memset(x,0,sizeof(x))
typedef int typev;
struct BIT{
    /* 设delta[i]表示[i,n]的公共增量 */
    typev *c1;    /* 维护delta[i]的前缀和 */
    typev *c2;    /* 维护delta[i]*i的前缀和 */
    typev *Sum;
    int n;
    BIT (){c1=c2=Sum=0;}
    void _clr(typev* &ar){
        if (ar) delete []ar;
        ar=new typev [n+10];
        memset(ar,0,sizeof(typev)*(n+10));
    }
    void init(int _n){
        n=_n;
        _clr(c1);
        _clr(c2);
        _clr(Sum);
    }
    typev query(typev *array, int i)
    {
        typev ret=0;
        while (i > 0) {
            ret += array[i];
            i -= lowbit(i);
        }
        return ret;
    }
    void update(typev *array, int i, typev d){
        while (i <= n) {
            array[i] += d;
            i += lowbit(i);
        }
    }
    void add(int s, int t, typev d)//将区间[s,t]所有元素加上d
    {
    /* 把delta[i](s<=i<=t)加d,策略是
        *先把[s,n]内的增量加d,再把[t+1,n]的增量减d
    */
        update(c1, s, d);
        update(c1, t+1, -d);
        update(c2, s, d*s);
        update(c2, t+1, -d*(t+1));
    }
    typev sum(int s, int t)//询问区间[s,t]的和
    {
        typev ret;
        ret = Sum[t] - Sum[s-1];
        ret += (t+1)*query(c1, t) - query(c2, t);
        ret -= (s*query(c1, s-1) - query(c2, s-1));
        return ret;
    }
}pool[55];
BIT *s[11][11];
BIT *test;

int main()
{
    int i, j, n, a, b, c, k, action, ans, Q, cnt=0, len;

    while ( ~scanf("%d",&n) )
    {
        //for (i=0; i<55; i++)
          //pool[i].init(n+4);
        for (i=1,cnt=0; i<=10; i++)
        {
            for (j=0; j<i; j++){
              s[j][i]=pool+cnt++;
              s[j][i]->init(n/i+10);
            }
        }

        for (i=1; i<=n; i++)
        {
            scanf("%d",&a);
            s[0][1]->add(i+1,i+1,a);
        }
        scanf("%d",&Q);
    while (Q--){
        scanf("%d",&action);
        if (action==2)
        {
            scanf("%d",&a);
            ans=0;
            for (i=1; i<=10; i++)
              ans+=s[a%i][i]->sum(a/i+1,a/i+1);
            printf("%d\n",ans);
        }
        else{
            scanf("%d %d %d %d",&a ,&b, &k, &c);
            len=(b-a)/k;
            s[a%k][k]->add(a/k+1,a/k+len+1,c);
        }
    }

    }
    return 0;
}


LianLianKan

这个是状压DP,据说贪心可以过。我dfs的时候用hash乱搞过掉。数据蛮水我会乱说?

#include <stdio.h>
#include <map>
#include <string.h>
#include <time.h>
using namespace std;
#define NN 1020
#define KK 2587219

clock_t tb,te;
int s[NN],dp[NN];
int hash[KK];
int fun(int n){
    if (n==-1) return 1;
    int tmp=0;
    bool b=0;
//    if (clock()-tb>1e7) return 0;
    for (int i=1;i<=5;i++){
        if (n-i<0) break;
        if (s[n]==s[n-i]){

            for (int j=n-i; j<=n-2; j++)
              s[j]=s[j+1];

            if (n-i-1>=0)  tmp=dp[n-i-1];else tmp=0;
            for (int k=n-i; k<=n-2; k++){
                tmp=(tmp+s[k]%KK*(k+2))%KK;
            }
            //b=b||fun(n-2);
            if (hash[tmp]==0) b=b||fun(n-2);
            else b=b||(hash[tmp]==-1?0:1);

            for (int j=n-1; j>=n-i+1; j--)
              s[j]=s[j-1];
            s[n-i]=s[n];

            if ( b==1 ) {
                hash[tmp]=1;
                return 1;
            }else hash[tmp]=-1;
        }
    }
    hash[dp[n]]=-1;
    return 0;
}

int main(){
    int T,n,i,j,k;
    while (scanf("%d",&n)!=EOF){
//        tb=clock();
        memset(dp,0,sizeof(dp) );
        memset(hash,0,sizeof(hash) );

        for (i=0;i<n;i++){
          scanf("%d",&s[i]);
          if (i>0) dp[i]=(dp[i-1]+s[i]%KK*(i+2) )%KK;
          else dp[0]=s[i]%KK*(i+2);
        }
//printf("hash=%d\n",dp[2]);
        if (n%2==1) {
            printf("0\n");
            continue;
        }
        printf("%d\n",fun(n-1) );

    }

    return 0;
}


 

USACO ORZ

这个真心ORZ了,不就是dfs之后hash么?随便算算搜索树也就1000w个叶子,怎么就无限tle。hash函数太烂,没去查冲突还wa了。

还是老老实实剪枝+hash吧,居然过了。

 

#include <cstdio>
#include <string.h>
#include <set>
//#include <map>
using namespace std;
//typedef int ll;
set<int> s;
//bool hash[(1<<24)+5];
int mod=0x00ffffff;
inline void adjust(int &a, int &b, int &c)
{
    int t;
    if (a<b){
        if (c<a) t=a,a=c,c=t;
        if (c<b) t=b,b=c,c=t;
    }else{
        if (b<c) t=a,a=b,b=t;else t=a,a=c,c=t;
        if (b<c) return;
        else t=b,b=c,c=t;
    }
}

int group[16],a[16],ans,n,len[4],tot;

bool cut(){
    int a=len[1],b=len[2],c=len[3],d=tot;
    adjust(a,b,c);
    if (a+b+d<=c) return false;
    //printf("%d %d %d %d\n",a,b,c,d);
    return false;
}
void dfs(int deep){
    if (deep>=n){
        {
            int a=len[1],b=len[2],c=len[3];
            //printf("%d %d %d\n",a,b,c);
            adjust(a,b,c);
            if (a==0 || a+b<=c) return ;
            int d;
            d=((a)*10009 + b);
            if (s.find(d)==s.end()){
                ans++;
                s.insert(d);
                //hash[d]=true;
                //printf("a=%d b=%d c=%d deep=%d\n",a,b,c,deep);
            }
        }
        return ;
    }
    int i=deep,j;
    if (group[i]==-1)
        for (j=1; j<4; j++){
            tot-=a[i];
            len[j]+=a[i];
            group[i]=j;

            if (!cut()) dfs(deep+1);

            group[i]=-1;
            len[j]-=a[i];
            tot+=a[i];
        }
}
int main()
{
    int i,T;
    scanf("%d",&T);
    while ( T-- ){
        memset(group,-1,sizeof(group));
        memset(len,0,sizeof(len));
        tot=ans=0;
        //memset(hash,0,sizeof(hash));
        s.clear();
        scanf("%d",&n);
        for (i=0; i<n; i++){
            scanf("%d",&a[i]);
            tot+=a[i];
        }

        len[1]=a[0];
        group[0]=1;
        tot-=a[0];
        dfs(1);
        tot+=a[0];
        group[0]=-1;
        len[1]=0;
        printf("%d\n",ans);
    }


    return 0;
}


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值