noip 아날로그 문제 소기 2 by hzwer [DP] [경로 압축] [분류 토론] [비트 연산]

이렇게 퇴락하다가는 조만간 끝날 것이다.
이 문제는 2h밖에 안 봤는데 괜찮은 것 같아요. T2가 비슷한 걸 해봤기 때문에 A를 했어요. T1과 T3도 기본적으로 큰 문제가 없어요. 관건은 문제의 특징을 깊이 파헤치는 거예요.분류 토론(많은 문제에서 많은 가지를 잘라낼 수 있다. 예를 들어 T1, 샤오치1의 T3, noip2015 day1 T3는 이런 분류 의식이 필요하다. T1: 제목: 좌표축에 약간의 수익이 있다. 0부터 물어보면 매번 4(0+4=4)보 또는 7(0+7=7)보만 앞으로 뛸 수 있다. 최대 수익은.데이터 범위: 20%의 데이터 n=1, m<=10^5는 40%의 데이터 n<=15, m<=10^5는 60%의 데이터 m<=10^5는 100%의 데이터 n<=10^5, m<=10^9, 1<=ai<=10^4, 1<=bi<=m 분석: 이 문제가 데이터 배분(또는 무엇, 뭐라고 하는지 모르겠다)의 전형적인 예인 것 같아서 황 학장은 이 두 문제를 잘 냈다.20%n=1, 갈 수 있는지 없는지만 보면 돼요.60%의 데이터는 m가 비교적 작아서 f[i]로 i의 이 위치의 최대치를 나타낼 수 있다. 그러면 -4, -7의 최대치를 찾아가면 된다.100%, 분석 결과, >=18의 상황은 반드시 갈 수 있습니다!그러면 18 이내에 수조로 저장해서 갈 수 있는지, 18 이외에 모두 갈 수 있으며, 갈 때 18 이내의 최대치를 갱신하면 됩니다!다음은 잔소리입니다. 보지 않아도 됩니다. 관건은 >=18의 그 성질을 발견하는 것입니다. 이것은 우리가 여러 손으로 규칙을 찾아야 한다는 요구입니다.이치대로 말하면 발견>=18 이후 100점 알고리즘은 순조롭게 이루어져야 하는데 나는 뜻밖에도 발견하지 못했고 이런 의식을 기르지 못했다.그리고 이 문제를 시험할 때 너무 zz했어요. 왜냐하면 제 알고리즘은 40점일 거예요. 뒤에 20점을 어떻게 받을지 고민을 많이 했는데 그 결과 문제풀이 보고서를 받아서 생각이 났어요. m을 매거하면 시간 복잡도 선형...
60분 프로그램:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define long long ll
#define inf 2e8
#define modd 1e9+7
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define each(i,n) for(int i=1;i<=n;i++)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "mining"
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int Maxn=1e5+5;
int n,m,ans,f[Maxn];
struct node
{
    int a,b;
}a[Maxn];
bool cmp(node x,node y)
{
    return x.aint read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void init()
{
    n=read();m=read();
    each(i,n){
        a[i].b=read();
        a[i].a=read();
    }
    sort(a+1,a+n+1,cmp);
}
int boo[20]={1,0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,1};
int check(int cur,int pre)
{
    if(cur-pre>=18)return 1;
    return boo[cur-pre];
}
void work()
{
    for(int i=1;i<=n;i++){
        int j=i-1;int flg=1;
        for(;j>=0;j--)if(check(a[i].a,a[j].a))
        f[i]=max(f[j]+a[i].b,f[i]);
        ans=max(ans,f[i]);
    }
    printf("%d",ans);
}
void debug()
{
    //
}
int main()
{
    freopen("hop.in","r",stdin);
    freopen("hop.out","w",stdout);
    init();
    work();
    //debug();
    return 0;
}

100점:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define long long ll
#define inf 2e8
#define modd 1e9+7
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define each(i,n) for(int i=1;i<=n;i++)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "mining"
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int Maxn=1e5+5;
int n,m,ans,maxn,f[Maxn];
struct node
{
    int a,b;
}a[Maxn];
bool cmp(node x,node y)
{
    return x.aint read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void init()
{
    n=read();m=read();
    each(i,n){
        a[i].b=read();
        a[i].a=read();
    }
    sort(a+1,a+n+1,cmp);
}
int boo[20]={1,0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,1};
int check(int cur,int pre)
{
    if(cur-pre>=18)return 1;
    return boo[cur-pre];
}
void work()
{
    for(int i=1;i<=n;i++){
        int j=i-1;
        for(;j>=max(0,i-17);j--)if(check(a[i].a,a[j].a))f[i]=max(f[j]+a[i].b,f[i]);
        if(i>18)maxn=max(maxn,f[i-18]);
        if(check(a[i].a,0))f[i]=max(f[i],maxn+a[i].b);
        ans=max(ans,f[i]);
    }
    printf("%d",ans);
}
void debug()
{
    //
}
int main()
{
    freopen("hop.in","r",stdin);
    freopen("hop.out","w",stdout);
    init();
    work();
    //debug();
    return 0;
}

T2: 제목: 권한 행렬의 왼쪽 상단에서 오른쪽 하단(아래로 또는 오른쪽으로만 갈 수 있음)으로 가세요.Σn+m -3. 1i=1(Ai -3. Aavg) 2의 최소값.분석: 우선, 우리는 하나의 서열에 대해 평균치가 틀리면 V값이 반드시 더 작다는 것을 증명할 수 있다. (구체적으로 어떻게 증명합니까? 길이가 2인 서열을 고려하여 그것을 뜯어 보세요. 이것은 균일치 부등식이 아닙니까?)그리고 이 권한 범위 <=30을 보세요. 한눈에 이상한 짓을 할 수 있어요.최소 정밀도에 따라 평균치를 매거하면 된다.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define long long ll
#define inf 2e8
#define modd 1e9+7
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define each(i,n) for(int i=1,i<=n;i++)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC ""
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int Maxn=305;
int t,n,m,lim,limi,ans,a[Maxn][Maxn],f[Maxn][Maxn];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void init()
{
   n=read();m=read();lim=n+m-1;
   for(int i=2;i<=n;i++)f[i][0]=inf;
   for(int j=2;j<=m;j++)f[0][j]=inf;
   for(int i=1;i<=n;i++)
       for(int j=1;j<=m;j++)
           a[i][j]=read()*lim;
   limi=lim*30;ans=2e9;
}
void work()
{
    for(int i=lim;i<=limi;i++){
        for(int j=1;j<=n;j++)
        for(int k=1;k<=m;k++)
            f[j][k]=min(f[j][k-1],f[j-1][k])+(a[j][k]-i)*(a[j][k]-i);
        ans=min(ans,f[n][m]);
    }
    printf("%d
"
,ans/lim); } void debug() { // } int main() { freopen("matrix.in","r",stdin); freopen("matrix.out","w",stdout); t=read(); for(int i=1;i<=t;i++){ init(); work(); } //debug(); return 0; }

T3: 제목: 한 그루의 나무에 대해 각 점에 대해 다른 점에서 이 점까지의 거리가 각각 다르거나 1치의 합을 구한다.분석: 사실은 다법도에서 발견할 수 있듯이 이 물건은 사실 마지막 몇 위의 01을 통계하여 해결할 수 있다.구체적인 실현은 0의 상황(즉 두 번의 dfs로 두 개의 그룹을 기록하는 것)을 처리하는 방법으로 01을 동시에 처리하면 된다는 것이다. 그러나 나는 당초에 너무 순진해서 폭력을 썼다.잔소리: 다fa도.폭력:(m!=0처리 잘못한 것 같아WA팀, 신에게 가르침을 구함)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 2e8
#define modd 1e9+7
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define each(i,n) for(int i=1;i<=n;i++)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC ""
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int Maxn=1e5+5;
int n,m,a,b,ans,roa[Maxn],g[Maxn],son[Maxn];
int f[Maxn],fr[Maxn],tov[2*Maxn],des[2*Maxn],wor[2*Maxn];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void addedge(int cur)
{
    a=read();b=read();wor[2*cur]=wor[2*cur-1]=read();
    tov[2*cur-1]=fr[a];fr[a]=2*cur-1;des[2*cur-1]=b;
    tov[2*cur]=fr[b];fr[b]=2*cur;des[2*cur]=a;
}
void dfs(int u,int fath,long long dis)
{
    if(dis)ans+=dis^m;
    for(int i=fr[u];i;i=tov[i])
        if(des[i]!=fath)
        dfs(des[i],u,dis+(long long)wor[i]);
}
void dfs2(int u,int fath)
{
    for(int i=fr[u];i;i=tov[i])
    if(des[i]!=fath){
        dfs2(des[i],u);
        roa[des[i]]=wor[i];son[u]+=1+son[des[i]];
        f[u]+=f[des[i]]+wor[i]*(son[des[i]]+1);
    }
}
void dfs3(int u,int fath)
{
    g[u]=f[fath]-f[u]+g[fath]+roa[u]*(n-son[u]*2-2);
    for(int i=fr[u];i;i=tov[i])
    if(des[i]!=fath)
        dfs3(des[i],u);
}
void init()
{
   n=read();m=read();
   for(int i=1;ivoid work()
{
    if(m)
    {
        for(int i=1;i<=n;i++){
            ans=0;dfs(i,0,0LL);
            printf("%d
"
,ans); } } else{ dfs2(1,0); f[0]=f[1];dfs3(1,0); for(int i=1;i<=n;i++) printf("%d
"
,f[i]+g[i]); } } void debug() { // } int main() { freopen("tree1.in","r",stdin); freopen("tree1.out","w",stdout); init(); work(); //debug(); return 0; }

좋은 웹페이지 즐겨찾기