This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int N = 500005;
const int MOD = 1e9 + 7;
const int SIGMA = 26;
void add(int &x, long long y){
y%=MOD;
x += y;
if(x >= MOD)
x-=MOD;
if(x<0)
x+=MOD;
}
struct dphelper{
int nways;
int lateless;
int latebig;
};
int lessthan[N];
int bigthan[N];
dphelper dp[N][SIGMA + 1][2][2];
const int INF = -1e9;
int fbg[N], fls[N];
void compute(int n){
vector<int> st;
st.push_back(n + 1);
lessthan[n + 1] = n + 1;
for(int i = n; i >=1; i--){
while(st.size() && lessthan[i] > lessthan[st.back()])
st.pop_back();
fls[i] = st.back();
st.push_back(i);
}
st.clear();
st.push_back(n + 1);
bigthan[n + 1] = n + 1;
for(int i = n; i >=1; i--){
while(st.size() && bigthan[i] > bigthan[st.back()])
st.pop_back();
fbg[i] = st.back();
st.push_back(i);
}
}
int main()
{
int n, m;
cin>>n>>m;
for(int i = 1; i<=m; i++){
int x, y;
cin>>x>>y;
if(x < y)
bigthan[x] = max(bigthan[x], y);
if(x > y)
lessthan[y] = max(lessthan[y], x);;
}
compute(n);
for(int i = 0; i<=n; i++){
for(int let = 0; let<=SIGMA; let++){
for(int tp1 = 0; tp1<=1; tp1++)
for(int tp2 = 0; tp2<=1; tp2++)
dp[i][let][tp1][tp2] = {0, INF, INF};
}
}
for(int let = 1; let<=SIGMA; let++){
int ls = 0, bg = 0;
if(lessthan[1])
ls = 1;
if(bigthan[1])
bg = 1;
if(ls == bg && ls == 1){
int lless, lbig;
lless = lessthan[1];
lbig = bigthan[1];
int mn = min(lless, lbig);
int futurels = 0, futurebg = 0;
if(lless - mn> 0)
futurels = 1;
if(lbig - mn> 0)
futurebg = 1;
if(futurels == 0 && futurebg == 0)
mn = min(mn, min(fls[1], fbg[1]));
else if(futurels == 0)
mn = min(mn, fls[1]);
else
mn = min(mn, fbg[1]);
add(dp[mn][let][futurels][futurebg].nways, 1); /// o sa se pastreze restul restrictiilor
if(futurels){
dp[mn][let][futurels][futurebg].lateless = max(dp[mn][let][futurels][futurebg].lateless, lless);
}
if(futurebg){
dp[mn][let][futurels][futurebg].latebig = max(dp[mn][let][futurels][futurebg].latebig, lbig);
}
}
else{
dp[1][let][ls][bg].nways = 1;
if(ls)
dp[1][let][ls][bg].lateless = lessthan[1];
if(bg)
dp[1][let][ls][bg].latebig = bigthan[1];
}
}
for(int i = 2; i<=n; i++){
/// propag pe i - 1, dupa pun restrictiile pt poz i noi si le scot pe cele vechi
/// propag fara restrictii
int total_sum = 0;
for(int let = 1; let <= SIGMA; let++)
add(total_sum, dp[i - 1][let][0][0].nways);
for(int let = 1; let <= SIGMA; let++){
add(dp[i][let][0][0].nways, total_sum);
}
total_sum = 0;
for(int let = SIGMA; let>= 1; let--){
add(dp[i][let][0][0].nways, total_sum); /// am pus mai mic si am scapat de restrictii
add(total_sum, dp[i - 1][let][1][0].nways);
if(dp[i - 1][let][1][0].lateless == i)
add(dp[i][let][0][0].nways, dp[i - 1][let][1][0].nways);
else{
add(dp[i][let][1][0].nways, dp[i -1][let][1][0].nways);
dp[i][let][1][0].lateless = max(dp[i][let][1][0].lateless, dp[i -1][let][1][0].lateless);
}
}
total_sum = 0;
for(int let = 1; let<= SIGMA; let++){
add(dp[i][let][0][0].nways, total_sum); /// am pus mai mare si am scapat de restrictii
add(total_sum, dp[i - 1][let][0][1].nways);
if(dp[i - 1][let][0][1].latebig == i)
add(dp[i][let][0][0].nways, dp[i - 1][let][0][1].nways);
else{
add(dp[i][let][0][1].nways, dp[i -1][let][0][1].nways);
dp[i][let][0][1].latebig = max(dp[i][let][0][1].latebig, dp[i -1][let][0][1].latebig);
}
}
/// bag restrictiile noi
for(int let = 1; let <=SIGMA; let++){
assert(dp[i][let][1][1].nways == 0);
for(int ls = 1; ls >=0; ls--){
for(int bg = 1; bg >=0; bg--){
int newls = ls, newbg = bg;
if(lessthan[i] > 0)
newls = 1;
if(bigthan[i] > 0)
newbg = 1;
if(newls == 1 && newbg == 1){
int lless, lbig;
lless = dp[i][let][ls][bg].lateless;
lbig = dp[i][let][ls][bg].latebig;
lless = max(lless, lessthan[i]);
lbig = max(lbig, bigthan[i]);
if(dp[i][let][ls][bg].nways){
int mn = min(lless, lbig);
int futurels = 0, futurebg = 0;
if(lless - mn> 0)
futurels = 1;
if(lbig - mn> 0)
futurebg = 1;
if(futurels == 0 && futurebg == 0)
mn = min(mn, min(fls[i], fbg[i]));
else if(futurels == 0)
mn = min(mn, fls[i]);
else
mn = min(mn, fbg[i]);
add(dp[mn][let][futurels][futurebg].nways, dp[i][let][ls][bg].nways); /// o sa se pastreze restul restrictiilor
if(futurels){
dp[mn][let][futurels][futurebg].lateless = max(dp[mn][let][futurels][futurebg].lateless, lless);
}
if(futurebg){
dp[mn][let][futurels][futurebg].latebig = max(dp[mn][let][futurels][futurebg].latebig, lbig);
}
}
dp[i][let][ls][bg] = {0, INF, INF};
}
else{
if(lessthan[i] > 0)
dp[i][let][newls][newbg].lateless = max(dp[i][let][newls][newbg].lateless, lessthan[i]);
if(bigthan[i] > 0)
dp[i][let][newls][newbg].latebig = max(dp[i][let][newls][newbg].latebig, bigthan[i]);
if((pair<int, int>){ls, bg} != (pair<int, int>){newls, newbg}){ /// cazul din 0 0 in cv ce nu e 1 0 sau 0 1
add(dp[i][let][newls][newbg].nways, dp[i][let][ls][bg].nways);
dp[i][let][ls][bg] = {0, INF, INF};
}
}
}
}
}
}
int ans = 0;
for(int let = 1; let<=SIGMA; let++){
add(ans, dp[n][let][0][0].nways);
add(ans, dp[n][let][0][1].nways);
add(ans, dp[n][let][1][0].nways);
}
cout<<ans;
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |