浙大2018省赛——重现赛(The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple)
题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=378
简单题就不写了。
============================================
E、LIS
一、题意
题目背景为LIS。现在已知$dp$数组,给定所有元素的上下界,要求构造满足条件的数组。Special Judge。
二、思路
不妨假设输入数据为$a[i]$。定义$c[i]$,表示:距离$a[i]$最近的且等于$a[i]-1$的元素位置。当$a[i]=1$时,那$c[i]$就随便了。$i$位置的上下界分别定义为$ub[i]$和$lb[i]$。
接下来,枚举所有的$dp$值,最小$1$,最大$n$。对于当前枚举的值$i$,找出$i$在$a$数组中的所有出现位置(可$O(n)$时间预处理出来),对于出现位置$p$,下标为$p$处的答案应该为:
如果$a[p]=1$,$ans[p]=max(lb[p],max{ans[j]}(p<j<=n&&a[j]=a[p]))$;
否则,$ans[p]=max(lb[p],max{ans[j]}(p<j<=n&&a[j]=a[p]), ans[c[p]]+1)$;
/*********************LaTeX解析不出来,难受,TT_TT*******************************/
此外,这题的上界在此思路中是没用的。因为这种思路可保证所求答案一定在上界内。
注意,这题卡常非常严重。清空记录位置的容器时,循环上界用$n$,别用$MAXN$。
三、代码
/********************template head********************/ #include<bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define mk(x, y) make_pair(x, y) #define pln() putchar('\n') #define cln() (cout << '\n') #define fst first #define snd second #define MOD 1000000007LL typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; const int MAXN = 1e5 + 10; template <class T> inline void read(T &x) { int t; bool flag = false; while((t = getchar()) != '-' && (t < '0' || t > '9')) ; if(t == '-') flag = true, t = getchar(); x = t - '0'; while((t = getchar()) >= '0' && t <= '9') x = x * 10 + t - '0'; if(flag) x = -x; } template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; } template<class T> T modpow(T a, T x, T mod) { T res = T(1); while(x > 0) { if(x & 1)res = (res * a) % mod; a = (a * a) % mod; x >>= 1; } return res; } /********************template head********************/ int n, a[MAXN], b[MAXN], c[MAXN], lb[MAXN], ub[MAXN], ans[MAXN]; vector<int> vs[MAXN]; int main() { #ifndef ONLINE_JUDGE // freopen("input.txt", "r", stdin); #endif // ONLINE_JUDGE int T; for(read(T); T--;) { read(n); for(int i = 1; i <= n; ++i)vs[i].clear(); for(int i = 1; i <= n; ++i) { read(a[i]); b[a[i]] = i; c[i] = b[a[i] - 1]; vs[a[i]].pb(i); } for(int i = 1; i <= n; ++i)read(lb[i]), read(ub[i]); for(int i = 1; i <= n; ++i) { int yb = -1; for(int j = vs[i].size() - 1; j >= 0; --j) { int p = vs[i][j]; ans[p] = max(lb[p], yb); if(a[p] != 1)ans[p] = max(ans[p], ans[c[p]] + 1); yb = ans[p]; } } for(int i = 1; i <= n; ++i)printf("%d%c", ans[i], i == n ? '\n' : ' '); } return 0; }
一、思路
预处理出$\frac{a[i]}{j}(1 \le i \le n, 1 \le j \le 30)$的前缀和。注意$j$的最大值,如果前缀和的类型为long long,$j$的上界取为$31$,会MLE。当然,可以用int,然后,在预处理前缀和的时候对$10^9$取模。但是,要注意,在求区间和的时候,要保证区间和为正。
然后,倍增+二分即可。
二、代码实现
/*--------------template head----------------*/ #include<bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define mk(x, y) make_pair(x, y) #define pln() putchar('\n') #define cln() (cout << '\n') #define fst first #define snd second #define MOD 1000000000LL typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; const int MAXN = 1e5 + 10; template <class T> inline void read(T &x) { int t; bool flag = false; while((t = getchar()) != '-' && (t < '0' || t > '9')) ; if(t == '-') flag = true, t = getchar(); x = t - '0'; while((t = getchar()) >= '0' && t <= '9') x = x * 10 + t - '0'; if(flag) x = -x; } template<class T> T gcd(T a, T b){ return b ? gcd(b, a % b) : a; } template<class T> T modpow(T a, T x, T mod){ T res = T(1); while(x > 0){ if(x & 1)res = (res * a) % mod; a = (a * a) % mod; x >>= 1; } return res; } /*--------------template head----------------*/ int a[500010],n,m; LL data[31][500010]; LL qzh(int ai,int aa,int b) { return data[ai][b]-data[ai][aa-1]; } int main() { //freopen("input.txt", "r", stdin); int T; LL p; cin>>T; while(T--) { LL ans=0; cin>>n>>m; for(int i=1;i<=n;i++) read(a[i]); sort(a+1,a+n+1); for(int i=1;i<=30;i++) { data[i][1]=a[1]/i; for(int j=2;j<=n;j++) data[i][j]=data[i][j-1]+a[j]/i; } for(int i=1;i<=m;i++) { LL sum=0; read(p); int bg=1,ed=1; LL ap=1; int qz=0; while(++qz) { if(ap>a[n]) break; ap*=p; ed=upper_bound(a+1,a+1+n,ap)-a; sum=sum+qzh(qz,bg,ed-1); //cout<<ap<<" "<<bg<<" "<<ed-1<<endl; sum%=MOD; bg=ed; } sum*=i; sum%=MOD; ans=ans+sum; ans%=MOD; } cout<<ans<<"\n"; } return 0; }
posted on 2018-05-02 20:50 鹤鸣于九皋,声闻于天 阅读(252) 评论(0) 编辑 收藏 举报