noip模擬63[被暴力爆了]
阿新 • • 發佈:2021-10-01
noip模擬63 solutions
不得不說,這兩天確實挺帶勁的
好像是因為我這兩天做的夢都被我記住了,高興的吧
昨天切了兩個,今天切了一個,但是波波好像又說我們菜了
但是今天還有一個點,T2的暴力沒有打,T3檔名點寫成逗號
導致我還沒有zxb暴力分高....
T1 電壓機制
這個首先觀察吧。。。
你發現這個可以沒有電流的邊一定在所有的奇數環中,一定不再任何一個偶數環中
所以你就直接搜就好了
直接差分記錄每個邊屬於多少個奇數環
但是還有一個條件是對偶數環的限制,所以我們遇到偶數環就減掉,保證不在任意一個偶數環中
雖然應該直接判斷是不是在偶數環中,但是這樣在奇數環的計數器中減掉相當於變相的把他變得不合法了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e5+5;
const int M=2e5+5;
int n,m,ans;
int to[M*2],nxt[M*2],head[N],rp=1;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
int dep[N],cir;
int ble[M*2],blp[N];
int vis[M*2],val[N];
void dfs(int x,int d){
dep[x]=d;
for(int i=head[x];i;i=nxt[i]){
if(vis[i])continue;
vis[i]=vis[i^1]=true;
int y=to[i];
if(dep[y]){
int tmp=dep[x]-dep[y]+1;
if(tmp&1){
ble[i]++;ble[i^1]++;
val[y]--;cir++;
}
else {
ble[i]--;ble[i^1]--;
val[y]++;
}
val[x]+=ble[i];
continue;
}
dfs(y,d+1);
ble[i]=ble[i^1]=val[y];
val[x]+=val[y];
}
}
signed main(){
#ifdef oj
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
scanf("%d%d",&n,&m);
fo(i,1,m){
int x,y;scanf("%d%d",&x,&y);
add_edg(x,y);add_edg(y,x);
}
dfs(1,1);
for(int i=2;i<=rp;i+=2)if(ble[i]==cir)ans++;
printf("%d",ans);
}
T2 括號密碼
這個題並不是難在你去分析每一步如何去做
而是難在你要如何拆分這個區間,讓他們變成許多互不相交但是可以包含的情況
這樣子之後就可以從小到大處理,一個區間一個區間的處理
那麼我們拆分的時候就直接將那些相交但是不包含的區間拆分成三個區間
然後我們對所有區間排好序,直接處理就好了
處理的時候先找到所有區間需要換啥,需要得到啥
先讓這些區間內部解決一下,然後再從外面進口
針對匹配不上的情況,直接內部交換就好了,實現的時候細節非常非常的多,結束了。。。
AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=2005;
char s[N];
int nn,n,len;
struct question{
int l,r;
question(){}
question(int x,int y){l=x;r=y;}
bool operator < (question a)const{
if(l==a.l)return r<a.r;
return l<a.l;
}
bool operator == (question a)const{
return l==a.l&&r==a.r;
}
}a[N],qus[N*N*5];
bool vis[N];
bool comp(question a,question b){
return a.r-a.l<b.r-b.l;
}
int in,ot,ans;
signed main(){
#ifdef oj
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
#endif
scanf("%s",s+1);len=strlen(s+1);
scanf("%d",&n);
fo(i,1,n){
scanf("%d",&a[i].l),a[i].l++;
vis[a[i].l]=true;
}
fo(i,1,n){
scanf("%d",&a[i].r),a[i].r++;
if(vis[a[i].r]){printf("-1");return 0;}
}nn=n;n=0;
fo(i,1,nn){
fo(j,1,nn){
if(a[i].l<a[j].l&&a[i].r>a[j].l&&a[i].r<a[j].r){
qus[++n].l=a[i].l;qus[n].r=a[j].l-1;
qus[++n].l=a[j].l;qus[n].r=a[i].r;
qus[++n].l=a[i].r+1;qus[n].r=a[j].r;
}
}
}
fo(i,1,nn)qus[++n].l=a[i].l,qus[n].r=a[i].r;
sort(qus+1,qus+n+1);n=unique(qus+1,qus+n+1)-qus-1;
sort(qus+1,qus+n+1,comp);
memset(vis,false,sizeof(vis));
fo(i,1,n){
int sum=0,mn=0;
fo(j,qus[i].l,qus[i].r){
if(vis[j])continue;
vis[j]=true;
if(s[j]=='(')sum++;
else sum--;
mn=min(mn,sum);
}
if(abs(sum)&1){printf("-1");return 0;}
if(sum>0)in+=sum/2;
else ot-=sum/2;
if(sum<0)mn-=sum;
if(mn<0){ans+=(abs(mn)+1)/2;}
}
int le=0,ri=0;
fo(i,1,len)if(s[i]=='('&&!vis[i])le++;
fo(i,1,len)if(s[i]==')'&&!vis[i])ri++;
if(in>ot&&ri<in-ot){printf("-1");return 0;}
if(in<ot&&le<ot-in){printf("-1");return 0;}
printf("%d",ans+max(in,ot));
}
T3 排列
這個考場上就想的是‘分治’,但是不是傳統意義上的,就是對24種情況分別做就行了
主要將對於特殊情況的 \(2\ 4\ 1\ 3\) 的這個不能找到一個可以將值域和位置都卡在別的地方的情況
所以我們列舉3,用一個樹狀陣列維護前面三個值
這裡我們要用到兩個樹狀陣列,我們再前面的序列中列舉4在哪裡,用樹狀陣列維護4前面的和後面的
維護的時候就每一次挪動4的位置,就更新左右兩側的樹狀陣列,這樣就可以了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define oj
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
const int N=2005;
int n,a[N],b[N],ans;
int pre[N][N];
struct BIT{
int tr[N];
void ins(int x,int v){
for(int i=x;i<=n;i+=(i&(-i)))tr[i]+=v;
}
int query(int x){
int ret=0;
for(int i=x;i;i-=(i&(-i)))ret+=tr[i];
return ret;
}
void clear(){memset(tr,0,sizeof(tr));}
}x,y;
signed main(){
#ifdef oj
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
#endif
scanf("%lld",&n);
fo(i,1,4)scanf("%lld",&a[i]);
fo(i,1,n)scanf("%lld",&b[i]);
if(a[1]==4&&a[2]==3&&a[3]==2&&a[4]==1)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==3&&a[2]==4&&a[3]==2&&a[4]==1)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==4&&a[2]==2&&a[3]==3&&a[4]==1)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==2&&a[2]==4&&a[3]==3&&a[4]==1)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==3&&a[2]==2&&a[3]==4&&a[4]==1)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==2&&a[2]==3&&a[3]==4&&a[4]==1)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==4&&a[2]==3&&a[3]==1&&a[4]==2)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==3&&a[2]==4&&a[3]==1&&a[4]==2)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==4&&a[2]==1&&a[3]==3&&a[4]==2)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==3&&a[2]==1&&a[3]==4&&a[4]==2)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==4&&a[2]==2&&a[3]==1&&a[4]==3)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
if(a[1]==4&&a[2]==1&&a[3]==2&&a[4]==3)reverse(a+1,a+4+1),reverse(b+1,b+n+1);
fo(i,1,n)pre[i][b[i]]=1;
fo(i,1,n)fo(j,1,n)pre[i][j]+=pre[i][j-1]+pre[i-1][j]-pre[i-1][j-1];
if(a[1]==1&&a[2]==2&&a[3]==3&&a[4]==4){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]>b[j])continue;
int tmp1=pre[i-1][b[i]-1]-pre[0][b[i]-1]-pre[i-1][0]+pre[0][0];
int tmp2=pre[n][n]-pre[n][b[j]]-pre[j][n]+pre[j][b[j]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==1&&a[2]==2&&a[3]==4&&a[4]==3){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]>b[j])continue;
int tmp1=pre[i-1][b[i]-1]-pre[0][b[i]-1]-pre[i-1][0]+pre[0][0];
int tmp2=pre[j-1][n]-pre[j-1][b[j]]-pre[i][n]+pre[i][b[j]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==1&&a[2]==3&&a[3]==2&&a[4]==4){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]<b[j])continue;
int tmp1=pre[i-1][b[j]-1]-pre[0][b[j]-1]-pre[i-1][0]+pre[0][0];
int tmp2=pre[n][n]-pre[j-1][n]-pre[n][b[i]]+pre[j-1][b[i]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==1&&a[2]==3&&a[3]==4&&a[4]==2){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]<b[j])continue;
int tmp1=pre[i-1][b[j]-1]-pre[0][b[j]-1]-pre[i-1][0]+pre[0][0];
int tmp2=pre[j-1][n]-pre[i][n]-pre[j-1][b[i]]+pre[i][b[i]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==1&&a[2]==4&&a[3]==2&&a[4]==3){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]<b[j])continue;
int tmp1=pre[i-1][b[j]-1]-pre[0][b[j]-1]-pre[i-1][0]+pre[0][0];
int tmp2=pre[n][b[i]-1]-pre[j][b[i]-1]-pre[n][b[j]]+pre[j][b[j]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==1&&a[2]==4&&a[3]==3&&a[4]==2){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]<b[j])continue;
int tmp1=pre[i-1][b[j]-1]-pre[0][b[j]-1]-pre[i-1][0]+pre[0][0];
int tmp2=pre[j-1][b[i]-1]-pre[i][b[i]-1]-pre[j-1][b[j]]+pre[i][b[j]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==2&&a[2]==1&&a[3]==3&&a[4]==4){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]>b[j])continue;
int tmp1=pre[j-1][b[i]-1]-pre[i][b[i]-1]-pre[j-1][0]+pre[i][0];
int tmp2=pre[n][n]-pre[j][n]-pre[n][b[j]]+pre[j][b[j]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==2&&a[2]==1&&a[3]==4&&a[4]==3){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]>b[j])continue;
int tmp1=pre[j-1][b[i]-1]-pre[i][b[i]-1]-pre[j-1][0]+pre[i][0];
int tmp2=pre[n][b[j]-1]-pre[j][b[j]-1]-pre[n][b[i]]+pre[j][b[i]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==2&&a[2]==3&&a[3]==1&&a[4]==4){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]<b[j])continue;
int tmp1=pre[i-1][b[i]-1]-pre[0][b[i]-1]-pre[i-1][b[j]]+pre[0][b[j]];
int tmp2=pre[n][n]-pre[j][n]-pre[n][b[i]]+pre[j][b[i]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==2&&a[2]==4&&a[3]==1&&a[4]==3){
fo(i,4,n){
x.clear();y.clear();
int sum=0;
fo(j,1,i-1)y.ins(b[j],1);
fo(j,1,i-2){
if(b[j]>b[i])ans+=sum;
else {
sum-=x.query(n)-x.query(b[j]);
sum+=y.query(b[j]-1);
y.ins(b[j],-1);
x.ins(b[j],1);
//cout<<sum<<" ";
}
}
}
}
if(a[1]==3&&a[2]==1&&a[3]==2&&a[4]==4){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]<b[j])continue;
int tmp1=pre[j-1][b[j]-1]-pre[i][b[j]-1]-pre[j-1][0]+pre[i][0];
int tmp2=pre[n][n]-pre[j][n]-pre[n][b[i]]+pre[j][b[i]];
ans+=tmp1*tmp2;
}
}
}
if(a[1]==3&&a[2]==2&&a[3]==1&&a[4]==4){
fo(i,1,n){
fo(j,i+1,n){
if(b[i]>b[j])continue;
int tmp1=pre[i-1][b[j]-1]-pre[0][b[j]-1]-pre[i-1][b[i]]+pre[0][b[i]];
int tmp2=pre[j-1][b[i]-1]-pre[i][b[i]-1]-pre[j-1][0]+pre[i][0];
ans+=tmp1*tmp2;
}
}
}
printf("%lld",ans);
}