简单分类讨论。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
int n;
cin>>n;
if(n&1){
cout<<0<<endl;
}else{
n>>=1;
if(n&1){
cout<<n/2<<endl;
}else{
cout<<n/2-1<<endl;
}
}
return 0;
}
贪心。就是找最小值之间的最大距离,我实现的时候把数组copy了一份放在后面,这样处理比较简单。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[400010];
int main(){
int n;
cin>>n;
int MIN=1e9+10;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
MIN=min(MIN,a[i]);
}
for(int i=1;i<=n;i++){
a[i+n]=a[i];
}
int pre=1;
int len=0;
for(int i=1;i<=n*2;i++){
if(a[i]==MIN){
len=max(len,i-pre-1);
pre=i;
}
}
ll ans = (ll)n*MIN+len;
cout<<ans<<endl;
return 0;
}
构造题。首先k=1很容易构造出来。k=x+1其实是由4个k=x构成的,用4个k=x拼起来后,把其中一个取反即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int a[1111][1111];
int main(){
int k;
cin>>k;
int n = 1<<k;
a[1][1]=1;
a[1][2]=1;
a[2][1]=1;
a[2][2]=0;
for(int i=2;i<=9;i++){
int half = 1<<(i-1);
for(int j=1;j<=half;j++){
for(int kk=1;kk<=half;kk++){
a[j][kk+half]=!a[j][kk];
}
}
//
for(int j=1;j<=half;j++){
for(int kk=1;kk<=half;kk++){
a[j+half][kk]=a[j][kk];
}
}
//
for(int j=1;j<=half;j++){
for(int kk=1;kk<=half;kk++){
a[j+half][kk+half]=a[j][kk];
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]){
printf("+");
}else{
printf("*");
}
}cout<<endl;
}
return 0;
}
这种题一看就知道是用map乱搞。大体思路是分开横向和纵向,先计算横向的,然后对于每个纵向的,看它穿过了多少个横向的,减去重叠部分即可。
一步一步来,首先是要把横向和纵向分开,同向的里面也有重叠的,把重叠的合并。然后简单计算一下所有横向的结果。计算完后,从左到右处理纵向的。对于枚举的每个纵向条条,维护有哪些横向的条条的横坐标包含了纵向条条的横坐标(我利用了map和priority_queue维护,具体见代码),然后利用树状数组(当然,事先离散化了Y坐标)计算它穿越了多少横向条条,把重叠部分减去即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n;
struct hor{
int x1,x2;
int y;
bool ban;
bool operator<(const hor& other)const{
if(y!=other.y){
return y<other.y;
}
if(x1!=other.x1){
return x1<other.x1;
}
return x2<other.x2;
}
}hors[100010];
bool cmpx1(hor a,hor b){
return a.x1<b.x1;
}
struct cmpx2{ //比较下x2
bool operator()(hor a,hor b){
return a.x2 > b.x2;
}
};
struct ver{
int y1,y2;
int x;
bool ban;
bool operator<(const ver& other)const{
if(x!=other.x){
return x<other.x;
}
if(y1!=other.y1){
return y1<other.y1;
}
return y2<other.y2;
}
}vers[100010];
int hcnt=0;
int vcnt=0;
map<int,int> ymp; //用于离散化
int c[200010];
inline int lowbit(const int &x){
return x&(-x);
}
void update(int x,int val){
while(x<200010){
c[x]+=val;
x+=lowbit(x);
}
}
int query(int x){
int ans = 0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
if(x1==x2){
vers[vcnt].y1=y1;
vers[vcnt].y2=y2;
vers[vcnt].x =x1;
vcnt++;
}else{
hors[hcnt].x1=x1;
hors[hcnt].x2=x2;
hors[hcnt].y =y1;
hcnt++;
}
ymp[y1]=0;
ymp[y2]=0;
}
sort(vers,vers+vcnt);
sort(hors,hors+hcnt);
//离散化
int kk = 1;
for(map<int,int>::iterator it = ymp.begin();it!=ymp.end();it++){
it->second = kk++;
}
//同向的合并
for(int i=1;i<vcnt;i++){
if(vers[i].x == vers[i-1].x){
if(vers[i].y1<=vers[i-1].y2){
vers[i].y1 = vers[i-1].y1;
vers[i].y2 = max(vers[i].y2,vers[i-1].y2);
vers[i-1].ban=1;
}
}
}
for(int i=1;i<hcnt;i++){
if(hors[i].y == hors[i-1].y){
if(hors[i].x1<=hors[i-1].x2){
hors[i].x1 = hors[i-1].x1;
hors[i].x2 = max(hors[i].x2,hors[i-1].x2);
hors[i-1].ban=1;
}
}
}
ll ans = 0;
//计算横向
for(int i=0;i<hcnt;i++){
if(!hors[i].ban){
ans+=hors[i].x2-hors[i].x1+1;
}
}
//处理纵向
sort(hors,hors+hcnt,cmpx1);
priority_queue<hor,vector<hor>,cmpx2> que;
int k=0;
for(int i=0;i<vcnt;i++){
if(vers[i].ban)continue;
//左边界符合的加入
while(hors[k].x1 <= vers[i].x && k < hcnt){
if(!hors[k].ban){
update( ymp[hors[k].y],1);
que.push(hors[k]);
}
k++;
}
//右边界不符合的移除
while(que.size()){
hor tmp = que.top();
if(tmp.x2 < vers[i].x){
que.pop();
update( ymp[tmp.y],-1);
}else{
break;
}
}
int q1 = query( ymp[vers[i].y1] - 1);
int q2 = query( ymp[vers[i].y2] );
ans+=(vers[i].y2 - vers[i].y1 + 1);
ans-=(q2-q1);
}
cout<<ans<<endl;
return 0;
}
线段树。线段树维护的是每个位置的字符,以及区间上,字符x紧接着字符y的次数(最多10*10组x,y)。对于每次询问,相当于得到了一个“字典序”,在线段树中查询,共有多少组相邻的字符xy,x的字典序小于y,记为sum,答案就是n-sum。因为n-repeat肯定是满足的,出现一次上述情况,可以省去一次。
#include <bits/stdc++.h>
using namespace std;
int n,m,k;
char str[200010];
struct node{
int l,r;
int ch;
int lazy;
int val[10][10];
}tree[800010];
void push_up(int x){
if(tree[x].l==tree[x].r)return;
node& lson = tree[x<<1];
node& rson = tree[(x<<1)|1];
for(int i=0;i<k;i++){
for(int j=0;j<k;j++){
tree[x].val[i][j] = lson.val[i][j]+rson.val[i][j];
}
}
}
int queryCh(int x,int pos){
if(~tree[x].lazy){
return tree[x].lazy;
}
if(tree[x].l==tree[x].r){
return tree[x].ch;
}
int mid = (tree[x].l+tree[x].r)>>1;
if(pos<=mid){
return queryCh(x<<1,pos);
}else{
return queryCh((x<<1)|1,pos);
}
}
void push_down(int x,int ch){
if(tree[x].l == tree[x].r){
tree[x].lazy = -1;
return;
}
node& lson = tree[x<<1];
node& rson = tree[(x<<1)|1];
lson.lazy = rson.lazy = tree[x].lazy;
tree[x].lazy = -1;
lson.ch = tree[x].ch;
rson.ch = tree[x].ch;
for(int i=0;i<k;i++){
for(int j=0;j<k;j++){
lson.val[i][j] = 0;
rson.val[i][j] = 0;
}
}
}
void updateVal(int x,int pos){
if(tree[x].l==tree[x].r){
if(tree[x].l){
memset(tree[x].val,0,sizeof(tree[x].val));
int left = queryCh(1,tree[x].l-1);
int ch = queryCh(1,tree[x].l);
if(left!=ch){
tree[x].val[left][ch] = 1;
}
}
return;
}
if(~tree[x].lazy){
push_down(x,tree[x].lazy);
}
int mid = (tree[x].l+tree[x].r)>>1;
if(pos<=mid){
updateVal(x<<1,pos);
}else{
updateVal((x<<1)|1,pos);
}
push_up(x);
}
void build_tree(int x,int l,int r){
tree[x].l = l;
tree[x].r = r;
tree[x].lazy = -1;
if(l==r){
if(l)tree[x].val[str[l-1]-'a'][str[l]-'a'] = 1;
tree[x].ch = str[l]-'a';
return;
}
int mid = (l+r)>>1;
build_tree(x<<1,l,mid);
build_tree((x<<1)|1,mid+1,r);
push_up(x);
}
void update(int x,int l,int r,int ch){
if(l==tree[x].l && r==tree[x].r){
tree[x].lazy = ch;
tree[x].ch = ch;
memset(tree[x].val,0,sizeof(tree[x].val));
return;
}
if(~tree[x].lazy){
push_down(x,tree[x].lazy);
}
int mid = (tree[x].l+tree[x].r)>>1;
if(mid>=r){
update(x<<1,l,r,ch);
}else{
if(mid<l){
update((x<<1)|1,l,r,ch);
}else{
update(x<<1,l,mid,ch);
update((x<<1)|1,mid+1,r,ch);
}
}
push_up(x);
}
int ans[11][11];
void query(int x,int l,int r){
if(l==tree[x].l && r==tree[x].r){
for(int i=0;i<k;i++){
for(int j=0;j<k;j++){
ans[i][j] += tree[x].val[i][j];
}
}
return;
}
if(~tree[x].lazy){
push_down(x,tree[x].ch);
}
int mid = (tree[x].l+tree[x].r)>>1;
if(mid>=r){
query(x<<1,l,r);
}else{
if(mid<l){
query((x<<1)|1,l,r);
}else{
query(x<<1,l,mid);
query((x<<1)|1,mid+1,r);
}
}
}
void Q(int l,int r){
memset(ans,0,sizeof(ans));
query(1,l,r);
}
int main(){
cin>>n>>m>>k;
scanf("%s",str);
build_tree(1,0,n-1);
while(m--){
int op;
scanf("%d",&op);
if(op==1){ //update
int l,r;
char chs[2];
scanf("%d%d%s",&l,&r,chs);
update(1,l-1,r-1,chs[0]-'a');
if(l-1)updateVal(1,l-1);
updateVal(1,r);
}else{ //query
char per[11];
scanf("%s",per);
Q(0,n-1);
bool tmp[11][11] = {0};
for(int i=0;i<k;i++){
for(int j=i+1;j<k;j++){
tmp[per[i]-'a'][per[j]-'a']=1;
}
}
int res = n;
for(int i=0;i<k;i++){
for(int j=0;j<k;j++){
if(tmp[i][j]){
res-=ans[i][j];
}
}
}
cout<<res<<endl;
}
}
return 0;
}