http://codeforces.com/contest/315
AB水题就不说了
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题意:定义一种变换。初始给出数组a[],每次对它进行变换,并且把d[i]<m并且i最小的数删掉(删掉之后后面的数往前移)。不能删除就停止。输出所有被删除数的初始下标。
题解:把di这个式子拆开,发现可以分成两部分bi,ci,b[i]可以由b[i-1]得到,c[i]可以O(1)获取。所以对a[]遍历一遍,求出d[i]就行。复杂度O(n)。还有一个注意事项见代码。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=200005;
ll a[N],b[N];
int main() {
int n,k;
while(~scanf("%d%d",&n,&k)) {
for(int i=1;i<=n;++i) scanf("%I64d",&a[i]);
int ans=0;
b[1]=0ll;
for(int i=2;i<=n;++i) {
//因为a[i-1]有可能已经被删掉了,所以式子不能这样化
//b[i]=b[i-1]+a[i-1]*(ll)(i-2-ans);
b[i]=b[i-1]+a[i]*(ll)(i-1-ans);
if(b[i]-(ll)(i-1-ans)*(ll)(n-i+1)*a[i]<k) {
printf("%d\n",i);
++ans;
b[i]=b[i-1];
}
}
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题意:定义有循环节的字符串的表示方法[str,n],比如[ab,2]=abab。首先给你两个用这种表示方法表示的字符串w,q,字符串[q.p]可以从w中获得,求最大的p。(ac可以从abc中获得)
题解:暴力方法肯定是扫一遍w串,如果w[i]==q[j],j就往后移。对于题目给出的有循环的字符串,我们可以对暴力方法进行优化。具体见代码。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=105;
char s1[N],s2[N];
int cnt[N],nex[N];
//从i出发经过了cnt[i]次结尾
//下一次要从nex[i]处开始
int main() {
int n,m;
while(~scanf("%d%d%s%s",&n,&m,s1,s2)) {
int len1=strlen(s1);
int len2=strlen(s2);
memset(cnt,0,sizeof(cnt));
memset(nex,0,sizeof(nex));
for(int i=0;i<len2;++i) {
int x=i;
for(int j=0;j<len1;++j) {
if(s1[j]==s2[x]) {
++x;
if(x>=len2) {
x=0;
++cnt[i];
}
}
}
nex[i]=x;
}
int ans=0,x=0;
for(int i=1;i<=n;++i) {
ans+=cnt[x];
x=nex[x];
}
printf("%d\n",ans/m);
}
return 0;
}
题意:找出给定数组中的所有非降子序列,求它们的乘积和。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int mod=1000000007;
const int N=1000020;
ll c[N],a[N/10],m;
int n;
void add(int k,ll val) {//arr[k]+=val;
while(k<=m) {
c[k]=(c[k]+val)%mod;
k+=k&-k;
}
}
ll read(int k) {//1~k的区间和
ll ans=0;
while(k) {
ans=(ans+c[k])%mod;
k-=k&-k;
}
return ans;
}
int main() {
while(~scanf("%d",&n)) {
m=0;
for(int i=1;i<=n;++i) {
scanf("%I64d",&a[i]);
m=max(m,a[i]);
}
memset(c,0,sizeof(c));
ll ans=0;
for(int i=1;i<=n;++i) {
ll t1=read(a[i]);
ll t2=(t1+1)%mod*a[i]%mod;
ll t3=t1-read(a[i]-1);//以a[i]结尾的
add(a[i],t2-t3);
}
printf("%I64d\n",read(m));
}
return 0;
}