[CodeForces939F]Cutlet

제목:


있다×n 2 × n의 시간에 양면의 고기를 구워주세요.
[li,ri] [l i,r i]
너는 이 구간의 시간 내에 임의로 이 고기를 뒤집을 수 있다
합법적인 방안이 존재하느냐고 물어보니 양면이 마침 n분밖에 안 구워졌어요.
최소 뒤집기 횟수를 구합니다
n≤105,k≤100 n ≤ 10 5 , k ≤ 100
폭력을 고려한 DP, fi, j D P, f i, j는 전 i i초, 구워지지 않은 면(반대편, 반대편은 정면)이 구워진 j 초의 최소 뒤집기 횟수를 나타낸다.
fi,j=fi -3 1,j f i,j = f i -3 1,j 뒤집지 않고 지난 상태 맞은편에서 j 초만 구웠어요.
fi,j=fi -3 1,i -3 j+1 f i,j = f i -3 1,i -3 j + 1 뒤집기, 현재 상태의 정면은 이전 상태의 정면,총 시간은 i,i,현재 정면은 j 초 굽기
이 폭력은 분명히 O(n2)O(n2)의 것이고 두 번째 전이는 [l,r][l,r] 내에서만 발생할 수 있다
O (nk) O (n k) 는 통과할 수 있고 이전 DP D P 의 첫 번째 이동은 거의 쓸모가 없으며, 중간 구간 밖의 빈 기어는 복제되어 지나간 것이다
그리고 모든 구간이 교차하지 않았다. ii구간의 오른쪽 단점은 rr로 설정했기 때문에 이런 DP,fi,jDP,fi,j는 전 r초를 표시하고 맞은편에서 jj초를 구운 최소 회전 횟수를 고려할 수 있다.
그리고 나서 우리는 한 구간에서 우리가 최대 두 번을 뒤집을 수 있고, 많은 것이 한 번 또는 두 번으로 바뀔 수 있다고 생각할 수 있다

한 번만 뒤집기.


한 시간 kk를 일일이 열거하면 뒤집힌 후의 정면이 k초간 더 구워졌다는 것을 나타낸다. k≤r-3 lk≤r-3 l
fi, j f i, j가 무엇으로 옮겨오는지 고민
현재 시간은 rr입니다. 그러면 현재 정면은 r-3 jr-3 j초를 구웠습니다. 왜냐하면 k초를 더 구웠기 때문입니다.
그래서 앞면을 뒤집으면 r-3-j-3-k-4-j-3-k초가 구워지고 또 뒤집히기 전에 앞면이 맞은편이에요.
fi,j=min{fi−1,r−j−k}+1 f i , j = m i n { f i − 1 , r − j − k } + 1
단조로운 대기열로 최우선 결정점 유지
k>r-3 l → pr-3 l→ p

두 번 뒤집기


똑같이 일일이 열거한 시간 kk는 뒤집힌 후의 정면이 k초간 구워졌다는 것을 나타낸다. k≤r-3 lk≤r-3 l
두 번 뒤집는 것이 현재의 맞은편을 뒤집는 것과 같다는 것을 감안하여 k초를 더 구운 후에 다시 뒤집었다
⇒fi,j=min{fi−1,j−k}+2 ⇒ f i , j = m i n { f i − 1 , j − k } + 2
마찬가지로 단조로운 대기열로 최우선 결정점 p=j - kp = j - k를 유지한다
k>r-3 l→ p< j-3 (r-3 l)k> r-3 l→ p< j-3 (r-3 l)일 때는 비합법적이며, 이것은 순차적으로 추진해야 한다는 것을 발견할 수 있다
이 DP D P 는 스크롤할 수 있습니다. 배열 크기에 주의하십시오.
#include
#define fp(i,a,b) for(register int i=a,I=b+1;i
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
templateinline bool cmax(T&a,const T&b){return a1:0;}
templateinline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
templateinline void sd(T&x){
    char c;T y=1;while(c=gc(),(c<48||571)if(c==45)y=-1;x=c-48;
    while(c=gc(),4758)x=x*10+c-48;x*=y;
}
const int N=2e5+5,inf=1e9;
typedef int arr[N];
int n,k,p;arr q,f[2];
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    sd(n),sd(k);int l,r,h,t;
    f[0][0]=0;fp(i,1,n)f[0][i]=inf;
    while(k--){
        sd(l),sd(r);p^=1;h=1,t=0;
        memcpy(f[p],f[p^1],sizeof f[p]);
        fp(j,0,min(n,r)){
            while(h<=t&&f[p^1][j]<=f[p^1][q[t]])--t;
            while(h<=t&&q[h]q[++t]=j;
            cmin(f[p][j],f[p^1][q[h]]+2);
        }h=1,t=0;
        fd(j,r,0){
            while(h<=t&&f[p^1][r-j]<=f[p^1][q[t]])--t;
            while(h<=t&&q[h]q[++t]=r-j;
            cmin(f[p][j],f[p^1][q[h]]+1);
        }
    }
    if(f[p][n]^inf)printf("Full
%d"
,f[p][n]); else puts("Hungry"); return 0; }

좋은 웹페이지 즐겨찾기