题目链接:http://codeforces.com/contest/1132/problem
第一题(思维):
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=1e2+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int cnt[4];
int main(){
rep(i,0,4) cin>>cnt[i];
if(cnt[2]==0){
if(cnt[0]==cnt[3]) puts("1");
else puts("0");
}
else{
if(cnt[0]==cnt[3]&&cnt[0]) puts("1");
else puts("0");
}
return 0;
}
第二题(模拟):
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=3e5+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
ll a[maxn];
ll n,m,sum=0;
ll b[maxn];
int main(){
cin>>n;
rep(i,0,n) {cin>>a[i];sum+=a[i];}
sort(a,a+n);
cin>>m;
rep(i,0,m){
cin>>b[i];
cout<<sum-a[n-b[i]]<<endl;
}
return 0;
}
第三题(思维+前缀和+暴力枚举):
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=5e3+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int n,q;
int l[maxn],r[maxn],tot=0;
int cnt[maxn],pre[maxn];///
int main(){
cin>>n>>q;
rep(i,0,q){
cin>>l[i]>>r[i];
cnt[l[i]]++,cnt[r[i]+1]--;
}
int ans=0,tmp;
rep(i,0,q){
tmp=tot=0;
cnt[l[i]]--,cnt[r[i]+1]++;
rep(j,1,n+1){
tmp+=cnt[j];///维护前缀和
if(tmp==1) pre[j]=pre[j-1]+1;
else pre[j]=pre[j-1];///维护覆盖数为1的前缀和
if(tmp) tot++;
}
rep(j,i+1,q){
ans=max(ans,tot-pre[r[j]]+pre[l[j]-1]);
}
cnt[l[i]]++,cnt[r[i]+1]--;
}
cout<<ans<<'\n';
return 0;
}
第四题(贪心+二分+优先队列+剪枝):
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=2e5+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
每个同学电脑有初始电量和电量消耗速度,
这堂课有k分钟,其损耗过程有note描述。
现在有个输出x,每分钟可以指定一个电脑并充电x,
问要维护每位同学电脑电量始终不小于零,其最小的x是多少。
题目分析:
这道题思路倒是蛮容易想的,就是细节比较多!
可以看出是二分,并且二分上界是12次方,题目凑好的,
不然过程中可能会有越界。
我们用优先队列维护过程中的电脑电量,
我们肯定优先选择支撑分钟最少的电脑,
如果电脑支撑分钟一样则无需细分,不难发现:
如果因为这次充电次数增加,那么下一次会轮到下一个最少的,
如果情况本身会超出界限,那么最终结果不会因为其顺序而影响,
关于这一点稍微模拟下不难发现。
那么对于每次取出来的节点,判定是否符合要求,如果符合则充电并再丢进去。
这里时间常数比较大,因为优先队列本身自带log,
下面是几个剪枝点:
上界可以预处理出来,这里我并没有这样做。。。
如果取出的最少次数都大于k那么一定可以成功(第二个if)
六十四位除法,关于次数的比较我们不要在优先队列的优先级比较里面写除法
而通过增加变量的方式来代替(重点:看来计组还是要好好学的。。。)
时间复杂度:O(nlog(1e12)*logn)
*/
ll n,k;
ll a[maxn],b[maxn];
struct node{
ll x,y,tim;
bool operator<(const node& q) const {
return tim>q.tim;///剪枝
}
};
bool judge(ll x){
priority_queue<node> pq;
rep(i,1,n+1) pq.push(node{a[i],b[i],a[i]/b[i]});
for(ll i=0;i<k;i++){
node tp=pq.top();pq.pop();
if(tp.x-i*tp.y<0) return false;
if(tp.x/tp.y>k) return true;///剪枝
tp.x+=x;pq.push(node{tp.x,tp.y,tp.x/tp.y});
}
return true;
}
int main(){
scanf("%lld%lld",&n,&k);
rep(i,1,n+1) scanf("%lld",&a[i]);
rep(i,1,n+1) scanf("%lld",&b[i]);
ll l=0,r=2e12;///这里还有一个加速点,可以预判定其上界
while(l<r){
ll mid=l+r>>1;
if(judge(mid)) r=mid;
else l=mid+1;
}
if(r==2e12) puts("-1");
else printf("%lld\n",r);
return 0;
}
第五题(背包优化):
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=1e5+100;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
给定八种物品每种物品价值为i,(1~8),
然后给定一个w,问能达到的不大于w的值最大值是多少。
w和物品个数都非常大。
题目分析:
比较神仙的一道背包题目吧算是,
我是看了题解才有想法的。
对于1到8,其单独取都可以凑成840(取八个数最小公倍数)
就是说假定答案是cnt1,cnt2,...cnt8,
那么我们总是可以从中剥离出840的整数倍,
这是答案的性质,利用这个性质我们进行优化。
因为我们对每一种答案都把840的整数倍剥离出来了,
所以最后实质上要进行的背包其容量最大是8*840,
然后每种物品个数也不超过840了,对于这个情况背包时间复杂度是允许的。
然后我们顺便维护下对于0到840中每一种最后达到的状态其取到的840的
个数的最大值,这就是传统的DP了,上面两个DP可以放到一起写,标志状态为-1即可。
然后对于8*840的每一种状态,我们都贪心的选取840来填充,其填充上界很明显是:
(w-j)/840,与dp数组中得出的值取最小即可,这样构成答案的候选者。
当然空间优化也是可以的。
*/
ll w;
ll cnt[8],dp[10][8*850];
int main(){
cin>>w;
rep(i,0,8) cin>>cnt[i];
mst(dp,-1),dp[0][0]=0;
rep(i,0,8) rep(j,0,8*840+1) if(dp[i][j]!=-1){
ll tmp=min(1LL*840/(i+1),cnt[i]);
rep(k,0,tmp+1)
dp[i+1][j+k*(i+1)]=max(dp[i+1][j+k*(i+1)],dp[i][j]+(cnt[i]-k)/(840/(i+1)));
}
ll ans=0;
rep(i,0,8*840+1) if(dp[8][i]!=-1){
if(i>w) continue;
ans=max(ans,i+min((w-i)/840,dp[8][i])*840);
}
cout<<ans<<'\n';
return 0;
}
第六题(区间DP):
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=5e2+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int n,tn=0,ans=0,INF;
char s[maxn];
int dp[maxn][maxn];
int main(){
scanf("%d%s",&n,s+1);
rep(i,1,n+1){
s[++tn]=s[i];
while(i+1<=n&&s[i+1]==s[i])
i++;
}
n=tn;
mst(dp,0xf),INF=dp[0][0];
rep(i,1,n+1) dp[i][i]=1;
rep(i,2,n+1) rep(j,1,n-i+2){
int l=j,r=j+i-1;
if(s[l]==s[r]) dp[l][r]=dp[l+1][r-1]+1;
else dp[l][r]=min(dp[l+1][r],dp[l][r-1])+1;
rep(k,l,r+1) dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]-1);
}
cout<<dp[1][n]<<'\n';
return 0;
}
第七题(线段树维护极值+DFS序+单调栈):
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=1e6+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int n,k,a[maxn];
int sk[maxn],l,r,rt=1e6+1;///虚点
vector<int> g[maxn];
int pl[maxn],pr[maxn],tot=0;
void dfs(int u,int pre){
pl[u]=++tot;
for(int i=0;i<g[u].size();i++){
if(g[u][i]==pre) continue;
dfs(g[u][i],u);
}
pr[u]=tot;
}
///线段树
int tree[maxn<<3],maxv[maxn<<3],lazy[maxn<<3];
void build(lrt){
lazy[rt]=0;
if(l==r) return ;
int mid=l+r>>1;
build(lson),build(rson);
}
void pushdown(int rt,int l,int r){
int mid=l+r>>1;
if(lazy[rt]){
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
maxv[rt<<1]+=lazy[rt];
maxv[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void update(lrt,int L,int R,int v){
if(L<=l&&r<=R){
maxv[rt]+=v;
lazy[rt]+=v;
return ;
}
pushdown(rt,l,r);
int mid=l+r>>1;
if(L<=mid) update(lson,L,R,v);
if(mid<R) update(rson,L,R,v);
maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
int query(lrt,int L,int R){
if(L<=l&&r<=R) return maxv[rt];
pushdown(rt,l,r);
int mid=l+r>>1,ans=0;
if(L<=mid) ans=max(ans,query(lson,L,R));
if(mid<R) ans=max(ans,query(rson,L,R));
return ans;
}
int main(){
cin>>n>>k;
l=1,r=l-1;
rep(i,1,n+1){
cin>>a[i];
while(r>=l&&a[sk[r]]<a[i]){
g[i].push_back(sk[r]);
g[sk[r]].push_back(i);
r--;
}
sk[++r]=i;
}
rep(i,l,r+1){
g[sk[i]].push_back(rt);
g[rt].push_back(sk[i]);
}
dfs(rt,0);///建立dfs序
build(1,tot,1);
rep(i,1,k+1) update(1,tot,1,pl[i],pr[i],1);
rep(i,1,n+2-k){
cout<<query(1,tot,1,1,tot)<<" ";
update(1,tot,1,pl[i],pr[i],-1);
if(i+k<=n)
update(1,tot,1,pl[i+k],pr[i+k],1);
}
return 0;
}